监听器与过滤器的区别,及执行规律与顺序

做了一个简单的测试,顺便让自己也深入了解了解。

话不多说,先创建类文件---new---class---add 输入要实现的接口

监听器大致分为三种级别的接口:

分别时 request  session ServletContext

下面弄个小测试,顺便看看执行的顺序与区别和之间的联系

request 声明周期太短,ServletContext生命周期又太长,还是用session,不短不长正好符合今天的测试

首先创建 一个类 sessionCreate 实现 HttpSessionListener 这个接口 的Create() 方法和Destroyed()方法

再配置web.xml文件

再创建一个类 sessionUpdate 实现 HttpSessionAttributeListener 接口的 Added() ,Removed() ,Replaced() 方法

省略配置步骤,基本上一样,只是包名与文件名的不同而已。

在创建过滤器,实现Filter 接口,跟上面创建监听器步骤基本一致

下面配置文件过滤器,基本上常用的是过滤页面的字符编码,还有登入权限的管理

如上图,<url-pattern>/login/*</url-pattern> 时指过滤login文件夹下的所有文件,当然也可以指定某个页面,不过我通常用这种方法,原因呢?好用呗,(后面具体会讲)

基本配置搞定,创建一个Entity实体类,用来储存数据,方便之后的展示数据,有个明确直观的效果,

接着在 sessionCreate  类中的 Create() 方法写上  System.out.println("创建session"); 输出语句,方便在控制台看到程序执行的顺序

省略其他几个方法和数据库  编写与配置步骤.....

编写index.jsp 页面

准备完成,然后在 tomcat 部署项目 ,点击调试,在每个方法中打上断点,运行,发现:

1.当服务运行时,就已经被实例化并执行FilterServlet 的 init() 方法

2.由于我的过滤页面时在login包下的,当执行index.jsp 页面时,index.jsp不在login包下,则不会执行Filter接口的doFilter()方法

然后在打开浏览器输入项目的 url 

之后我又尝试以不同的浏览器打开,然后关闭,发现紧接着后面输入了一句   创建session,从而可以说明,当服务器开启之后,

3.每打开一个新的会话, sessionCreate  类中的 Create() 方法会被调用一次,

而关闭浏览器却没有 输出session被销毁,为什么呢?翻看其他的资料,发现: 除了手动的设置session 的最大非活动时间,或者立即销毁,在tomcat的conf文件的web.xml文件默认设置了session非活动的最长时效,默认30分钟

然后输入账号密码,进行登入-------------------------------------------------------------------

还没有进去登入成功的页面

Console 输出这样的结果:

这说明:

3.Servlet  首先被实例化,然后初始化,在根据form表单提交的方式执行 doPost()方法或doGet()方法,通常表单提交都是doPost(),我这里提交方式就用doPost()

紧接着 在superManagerServlet 这个过滤页面(处理数据与逻辑) 输出了System.out.println("servlet的doPost方法被执行")

调用查询方法查询数据库信息,实例化实体类对象去储蓄用户输出的数据,把用户数据保存到session里面,通过session.setAttribute("user", user);保存到session 域中,

结果一直都没有输出 System.out.println("添加session用户信息");为什么呢?原来,我保存的user 用户信息为null,导致没有执行session.setAttribute("user", user); 当session调用set 方法保存数据时,当数据为null 时,就会出现设置的数据为空,(我想是不是session底层的数据处理,为节省减少服务器的压力,session底层下时怎么处理数据的还有待研究)

弄好之后如图:

4.session.setAttribute() 设置储存数据时,会调用HttpSessionAttributeListener这个接口下的 attributeAdded()方法

5.保存完数据之后,程序又走到 Filter接口类的的doFilter()方法中,去执行页面过滤

这就是我在web.xml配置 filter 文件时 获取文件路径 /login/* 包下的原因了,当执行index.jsp 页面时,因为不在 这个login包下,则不会去过滤index.jsp页面,不然你也可以试试(会报错误,重定向次数过多,除非你就过滤页面字符的编码,不过这样就没必要使用这个过滤器了,还不如直接在页面用小代码块直接写request设置字符编码.....)

根据业务需求,进行逻辑判断显示登入之后的页面

当设置了session的最大非活动时间,这些基本流程走完之后就是默默的等待session的失效了

6.当设置了session 的有效时长之后,会先执行HttpSessionListener 接口的 Destroyed() 方法 销毁session,这里的销毁不是真正意义上的销毁,只是让数据为空(说错了请谅解,只是我对这个方法的个人理解)

当执行 Destroyed() 这个方法之后

  

7.再执行HttpSessionAttributeListener 这个接口的Removed()方法去真正意思上的销毁(删除)


哦,对了,还有一个方法没有讲到,就是HttpSessionAttributeListener 这个接口的Replaced()方法,那么他会在什么时候被执行呢?

 再打开另外一个浏览器去测试

如图:

 

 

从图中我们可以清晰的看到Console 的输出结果以及执行顺序

第一个浏览器打开之后创建session之后和第二个浏览器打开之后创建session之后都是执行HttpSessionAttributeListener的 Added()而没有执行Replaced()方法,

因为浏览器打开之后产生唯一的sessionid,而浏览器不同产生的sessionid 也不同,session都是通过这个唯一标识去操作数据的

那么什么时候会执行 Replaced()方法呢?

再次测试(以Google为例),我登入账号密码之后,再关闭浏览器再打开Google,再次登入

 

 

Console的输出结果如下

 

看到输出结果,大家就应该明白了把?我通过session.setAttribute("user", user);设置的用户信息,再次被调用session设置保存数据时,则会调用HttpSessionAttributeListener的Replaced()方法

也就是说,set的对象名相同则会调用Replaced去替换原来的session对象

这就是基本的监听器与过滤器的执行流程

 

servlet过滤器的生命周期:

  服务开启时实例化

  ->初始化

  ->浏览器发送请求

  ->访问公共service方法,而当每次向服务器发送请求页面时,则会调用doFilter()方法去执行页面的过滤

  ->访问私有servlet方法

  ->调用doGetI()/doPost()

  ->当关闭服务器的时候就会调用destroy方法销毁过滤器。

ServletSession监听器的生命周期:

  ->打开浏览器时(创建session对象,生成唯一sessionid)

  ->使用setAttribute保存属性时

  ->调用add()

  ->重复设置session的对象时则会调用Replaced()方法

  ->设置非活动时长/默认有效时长

  ->调用 Destroyed() 方法 销毁session

  ->Removed()删除session

区别:

  过滤器:

    1.当服务器接受请求时被触发,初始化一次

    2.服务器加载时就已经加载成功了,时时刻刻等待服务器的响应 

       3.只有当你的web应用停止或重新部署的时候才销毁

    4.公有实现的接口Filter 私有:HttpServlet

  监听器,以session为例

    1.服务器加载完毕,产生一个新的会话时(当然别的对象还没又尝试过,不过我想的时,服务器启动完毕之后它才会被启动把)

    2.当对象的属性被修改时触发时

    3.Servlet的监听器Listener的九大接口

联系:

   过滤器Filter 依赖于Servlet容器,基于回调函数,过滤范围大

作用:

  过滤器:主要用于,业务逻辑的页面跳转处理和字符编码设置,减轻服务器负载,压力

  监听器:主要用于,做一些初始化的内容添加工作、设置一些基本的内容、比如一些参数或者是一些固定的对象等等

配置问题:

  过滤器执行的顺序是按照,web.xml中filter-mapping标签的书写顺序执行(从上往下执行,不确定,自己没测试过,改天有机会测试)

  共同点: 监听器、过滤器一般配置在web.xml中

  不同点:  一个应用中可以配置多个过滤器,而监听器时对应的实现接口

执行顺序:

  创建: 监听器-->过滤器-->Servlet.
  销毁: 过滤器-->Servlet-->监听器

大致上就是这样,如有不对之处,批评指正,虚心求教.....

 

posted @ 2018-01-23 15:28  得_失之我幸  阅读(504)  评论(0编辑  收藏  举报