过滤器监听器上下文servlet线程安全问题.docx

上传人:b****7 文档编号:11197978 上传时间:2023-02-25 格式:DOCX 页数:18 大小:364.22KB
下载 相关 举报
过滤器监听器上下文servlet线程安全问题.docx_第1页
第1页 / 共18页
过滤器监听器上下文servlet线程安全问题.docx_第2页
第2页 / 共18页
过滤器监听器上下文servlet线程安全问题.docx_第3页
第3页 / 共18页
过滤器监听器上下文servlet线程安全问题.docx_第4页
第4页 / 共18页
过滤器监听器上下文servlet线程安全问题.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

过滤器监听器上下文servlet线程安全问题.docx

《过滤器监听器上下文servlet线程安全问题.docx》由会员分享,可在线阅读,更多相关《过滤器监听器上下文servlet线程安全问题.docx(18页珍藏版)》请在冰豆网上搜索。

过滤器监听器上下文servlet线程安全问题.docx

过滤器监听器上下文servlet线程安全问题

过滤器、监听器、上下文、servlet线程安全问题

过滤器:

什么是过滤器:

servlet规范当中定义的一种特殊的组件,用来拦截servlet容器的调用过程。

会先调过过滤器的方法,过滤器决定是否向后继续调用就是调用servlet容器

容器收到请求之后通常情况下会调用servlet的service方法来处理请求。

如果有过滤器,则容器先调用过滤器的方法

如何写一个过滤器:

1、写一个Java类,实现接口Filter

2、在doFilter方法里面,编写拦截处理逻辑

3、配置过滤器(web.xml)让容器知道哪些请求需要拦截

比如写一个评论,然后显示出来。

但是说一些敏感字。

就不允许其评论

但是已经写完了的话,评论与后端的servlet的话。

可以直接加个过滤器

容器只要一启动,就会立即创建过滤对象。

只会创建一个。

容器在创建过滤器对象之后会调用该对象的init方法。

该方法只会执行一次。

容器调用doFilter方法来处理请求

FilterChain(过滤器链)

过滤器

CommentFilterA

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.Filter;

importjavax.servlet.FilterChain;

importjavax.servlet.FilterConfig;

importjavax.servlet.ServletException;

importjavax.servlet.ServletRequest;

importjavax.servlet.ServletResponse;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

publicclassCommentFilterAimplementsFilter{

publicvoiddestroy(){

//TODOAuto-generatedmethodstub

}

//容器会将request和response作为参数传递过来。

//下面两个arg0和arg1就是但是是Servlet的。

用的是其子类HttpServlet。

那么就强制转换成其子类

//如果调用了FilterChain的doFilter方法,则容器会继续向后调用,如果没有调用doFilter就爱不会继续向后调用

publicvoiddoFilter(ServletRequestarg0,ServletResponsearg1,

FilterChainarg2)throwsIOException,ServletException{

//TODOAuto-generatedmethodstub

HttpServletRequestrequest=(HttpServletRequest)arg0;

HttpServletResponseresponse=(HttpServletResponse)arg1;

request.setCharacterEncoding("utf-8");

Stringcontent=request.getParameter("content");

if(content.indexOf("日")!

=-1){

//包含了敏感字

PrintWriterout=response.getWriter();

out.print("!

!

!

yourcommnetiserror");

return;

}else{

//没有,继续向后调用

arg2.doFilter(arg0,arg1);

}

}

publicvoidinit(FilterConfigarg0)throwsServletException{

//TODOAuto-generatedmethodstub

}

}

一定要记得配置!

web.xml

--配置过滤器-->

filterA

web.CommentFilterA

filterA

/*这个就是访问什么url就会通过过滤器写的评论是将评论内容发向process的,所以~我写了个*.jsp就根本不能访问了!

哈哈哈*/

/process

练习:

评论的字符的个数有限制

写一个过滤器,检测评论的字符的个数,如果超过10个,则提示评论的字数过多。

CommentFilterB.java

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.Filter;

importjavax.servlet.FilterChain;

importjavax.servlet.FilterConfig;

importjavax.servlet.ServletException;

importjavax.servlet.ServletRequest;

importjavax.servlet.ServletResponse;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

publicclassCommentFilterBimplementsFilter{

publicvoiddestroy(){

//TODOAuto-generatedmethodstub

}

publicvoiddoFilter(ServletRequestarg0,ServletResponsearg1,

FilterChainarg2)throwsIOException,ServletException{

//TODOAuto-generatedmethodstub

HttpServletRequestrequest=(HttpServletRequest)arg0;

HttpServletResponseresponse=(HttpServletResponse)arg1;

request.setCharacterEncoding("utf-8");

Stringmessage=request.getParameter("content");

PrintWriterout=response.getWriter();

if(message.length()>10){

out.print("

评论字数不得超过10个!

");

return;

}else{

arg2.doFilter(arg0,arg1);

}

}

publicvoidinit(FilterConfigarg0)throwsServletException{

//TODOAuto-generatedmethodstub

}

}

过滤器的优先级

当有多个过滤器都满足过滤的条件,则容器会依据的先后顺序来调用。

但是这么的就固定限制了,只能是日和10个。

那么就~

--初始化参数-->

illegalStr

日你

在配置文件中先配置好,然后去读取初始化参数

更改CommentFilterA.java过滤器

就是给init增加一个属性,因为init执行一次就没了。

那么变量也没了。

创建一个全局变量来存储容器传进来

的FilterConfig对象

然后在方法中读取配置文件中对应名字的内容

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.Filter;

importjavax.servlet.FilterChain;

importjavax.servlet.FilterConfig;

importjavax.servlet.ServletException;

importjavax.servlet.ServletRequest;

importjavax.servlet.ServletResponse;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

publicclassCommentFilterAimplementsFilter{

privateFilterConfigconfig;

//用config来存储init中的读取初始化参数的对象。

publicvoiddestroy(){

}

//容器会将request和response作为参数传递过来。

//下面两个arg0和arg1就是但是是Servlet的。

用的是其子类HttpServlet。

那么就强制转换成其子类

//如果调用了FilterChain的doFilter方法,则容器会继续向后调用,如果没有调用doFilter就爱不会继续向后调用

publicvoiddoFilter(ServletRequestarg0,ServletResponsearg1,

FilterChainarg2)throwsIOException,ServletException{

//TODOAuto-generatedmethodstub

HttpServletRequestrequest=(HttpServletRequest)arg0;

HttpServletResponseresponse=(HttpServletResponse)arg1;

request.setCharacterEncoding("utf-8");

Stringcontent=request.getParameter("content");

Stringmingan=config.getInitParameter("illegalStr");

if(content.indexOf(mingan)!

=-1){

//包含了敏感字

PrintWriterout=response.getWriter();

out.print("!

!

!

yourcommnetiserror");

return;

}else{

//没有,继续向后调用

arg2.doFilter(arg0,arg1);

}

}

publicvoidinit(FilterConfigarg0)throwsServletException{

//TODOAuto-generatedmethodstub

//将容器传递过来的FilterConfig对象保存下来

config=arg0;

}

}

过滤器优点

1、不用修改原有程序,在原有程序上增加一些新的功能。

2、将多个组件相同的处理逻辑集中写在过滤器里面,方便代码的维护。

(比如登陆,可以把验证写在过滤器里)

监听器

什么是监听器:

servlet规范当中定义的一种特殊的组件,用来监听容器产生的事件的。

容器会产生什么事件:

主要有两大类:

1、生命周期相关的时间

容器创建或者销毁了request,session,servlet,上下文时产生的事件。

比如说现在有多少人在访问应用,session是用来保存状态的。

只用统计session的个数。

他的创建和销毁,做个监听器进行监听

2、绑定数据相关的事件

调用了request,session,servlet上下文的setAttribute,removeAttribute时产生的事件。

servlet上下文

什么是servlet上下文

容器启动之后,会为每一个web应用创建唯一的一个符合ServletContext接口要求的对象

特点:

一个web应用对应一个唯一的上下文

只要容器没有关闭,并且应用没有被删除,则上下文会一直存在。

如何获得上下文

4种方式

GenericServlet,ServletConfig,FilterConfig,HttpSession提供了一个getServletContext方法来获得上下文。

作用:

1、绑定数据

setAttribute,getAttribute,removeAttribute

注:

将数据绑定到上下文上面,可以随时访问。

因为他一直在。

转发

request.setAttribute

绑定到session上

session.setAttrobute

也可以ServletContext.setAttribute

绑定的不同上面不同,ServletContext时间最长,但是占用内存。

所有优先使用保存时间短的即request

在满足使用条件的情况下,优先使用生命周期短的

(request

例子:

先写一个ServletA来在上下文中绑定数据,然后在ServletB中读取数据。

这个数据是随web应用的结束而结束,就算浏览器关闭了也还在。

ServletA:

 

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.ServletContext;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

publicclassAextendsHttpServlet{

publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)

throwsServletException,IOException{

response.setContentType("text/html");

PrintWriterout=response.getWriter();

//先获得上下文

ServletContextctx=getServletContext();

//将一些数据绑定到上下文

ctx.setAttribute("userlist","ddd,qqq,lihaile");

out.close();

}

}

ServletB:

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.ServletContext;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

publicclassBextendsHttpServlet{

publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)

throwsServletException,IOException{

response.setContentType("text/html");

PrintWriterout=response.getWriter();

//获得上下文

ServletContextctx=getServletContext();

Stringuserlist=(String)ctx.getAttribute("userlist");

out.print("

"+userlist+"

");

out.close();

}

}

2、访问全局的初始化参数

--全局的初始化参数-->

company

Recar

然后读取全局的初始化参数:

StringgetInitParamenter(StringparamName);

如何写一个监听器:

1、写一个java类实现相应的接口

要根据监听的事件类型来选择合适的接口。

比如,要监听session的创建和销毁,需要实现HttpSessionListener接口

2、在这个接口方法当中,实现监听处理逻辑

3、配置web.xml

例子:

实现统计在线人数

把count这个数据绑定到山下文中。

通过session事件的创建于销毁来检测当前在线人数,创建则加,销毁则减

用一个浏览器看就是在线人数1,我用了3个浏览器看就变成3个了。

一个浏览器在开新窗口还是人数不会变的,因为无论开多少窗口都会用那个session的

sessionId会保存在内存中。

增加登出。

就是销毁session

再写一个servlet来登出,就是删除其session。

触发session销毁事件,减少一个在线人数

监听器:

Countlister.java

packageweb;

importjavax.servlet.ServletContext;

importjavax.servlet.http.HttpSession;

importjavax.servlet.http.HttpSessionEvent;

importjavax.servlet.http.HttpSessionListener;

publicclassCountlistenerimplementsHttpSessionListener{

/*

*session对象创建之后,容器会调用此方法

*/

publicvoidsessionCreated(HttpSessionEventarg0){

//TODOAuto-generatedmethodstub

//获得上下文,先通过session事件对象来获取session

HttpSessionsession=tSession();

ServletContextctx=session.getServletContext();

Integercount=(Integer)ctx.getAttribute("count");

if(count==null){

count=1;

}else{

count++;

}

ctx.setAttribute("count",count);

 

}

/*

*session对象销毁之后,容器会调用此方法。

*/

publicvoidsessionDestroyed(HttpSessionEventarg0){

 

HttpSessionsession=arg0.getSession();

ServletContextctx=session.getServletContext();

Integercount=(Integer)ctx.getAttribute("count");

count--;

ctx.setAttribute("count",count);

}

}

显示当前在线人数:

当前在线人数:

<%=application.getAttribute("count")%>

登出!

登出,销毁session类

LogoutServlet.java

packageweb;

importjava.io.IOException;

importjava.io.PrintWriter;

importjavax.servlet.ServletContext;

importjavax.servlet.ServletException;

importjavax.servlet.http.HttpServlet;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importjavax.servlet.http.HttpSession;

publicclassLogoutServletextendsHttpServlet{

 

publicvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)

throwsServletException,IOException{

HttpSessionsession=request.getSession();

session.invalidate();

}

}

servlet线程安全问题

为什么说servlet会存在线程安全问题?

容器收到请求会启动一个线程

当有多个线程访问一个方法。

packageweb;

importjava.io.IOException;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1