Servlet编程专题9之Servlet规范中的过滤器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Servlet编程专题9之Servlet规范中的过滤器相关的知识,希望对你有一定的参考价值。

1、Filter基础:

-  Filter是Servlet规范的三大组件之一。顾名思义,就是过滤。可以在请求到达目标资源之前先对请求进行拦截过滤,即对请求进行一些处理;也可以在响应到达客户端之前先对响应进行拦截过滤,即对响应进行一些处理。

技术分享


2、Filter的生命周期:

a、Filter的生命周期与Servlet的生命周期类似,其主要生命周期阶段有四个:Filter对象的创建、Filter对象的初始化、Filter执行doFilter()方法以及最终Filter对象被销毁。

-   Filter的整个生命周期过程的执行,均由Web服务器负责管理。即Filter从创建到销毁的整个过程中方法的调用,都是由Web服务器负责调用执行的,程序员无法控制其执行流程。

技术分享


-  过滤器生命周期示例:

-  自定义的Filter类需要实现Filter接口(javax.servlet.Filter),并实现其接口中定义的方法:

技术分享


-  自定义Servlet类:

技术分享


-  需要注意的是,需要在web.xml中注册filter:

技术分享


-  启动服务器,访问项目中的/some路径资源,在控制台中显示的结果为其生命周期:

技术分享

技术分享


-  上例中的接口以及方法的解释:

-  javax.servlet.Filter接口:过滤器是用于过滤请求资源(servlet、静态资源)或者是从资源响应客户端的过滤任务:(或者是两者兼而有之)

技术分享

-  其接口中三个定义方法:

技术分享


- javax.servlet.FilterChain接口:FilterChain接口类对象是被用于servlet容器提供给开发者从视图到资源过滤请求的调用链的对象。过滤器使用过滤器链来调用链中的下一个过滤器,如果正在调用的过滤器是链中的最后一个,则会直接调用链末尾端的资源。

技术分享

-  该接口中只定义一个方法:调用过滤器链中的下一个过滤器,或者如果正在调用的过滤器是链中的最后一个,则会直接调用链末尾端的资源。

技术分享


b、Filter的特征:

-  Filter是单例多线程的。

-  Filter是在应用被加载时创建并初始化的,这是与Servlet不同的地方。Servlet是在该Servlet被第一次访问时创建的。Filter与Servlet的共同点是,其无参构造器与init()方法只会执行一次。

-  用户每提交一次该Filter可以过滤的请求,服务器就会执行一次doFilter()方法,即doFilter()方法可以被多次执行。

-  当应用被停止时执行destroy()方法,Filter被销毁,即destroy()方法只会执行一次。

-  由于Filter是单例多线程的,所以为了保证其线程安全性,一般情况下是不为Filter类定义可修改的成员变量。因为每个线程均可修改这个成员变量,会出现线程安全问题。


3、javax.servlet.FilterConfig接口:通常指代filter在web.xml中的注册信息:

技术分享

-  FilterConfig接口中的方法可以获取关于当前Filter在web.xml中的信息:(ServletContext、filterName、initParameter等):

技术分享


-  FilterConfig接口中的方法在filter类中使用的示例:

-  可以在自定义Filter类中定义私有化的成员变量(并提供getFilterConfig()方法),在init(FilterConfig filterConfig)方法接收。在doFilter方法中使用这个filterConfig成员变量:

技术分享


-  需要注意的是,在web.xml中的<filter>标签中,可以提供<init-param>标签,以提供初始化参数:

技术分享

-  当访问一个index.jsp页面时,控制台中的打印如下:

技术分享


4、<dispatcher>标签的四种取值:

-  在<filter-mapping>中还有一个子标签<dispatcher>,用于设置过滤器的请求类型。其有四种取值,REQUEST、FORWARD、INCLUDE、ERROR。

-  FORWARD:若请求是由一个Servlet通过RequestDsipatcher的forward()方法所转发的,那么这个请求将被<dispatcher>值为FORWARD的Filter所拦截。即当前Filter只会拦截由RequestDispatcher的forward()方法所转发的请求。其他请求均

不拦截。

技术分享


-  INCLUDE:当前Fillter只会拦截由RequestDsipatcher的include()方法所转发的请求。其他请求均不拦截。

技术分享


-  REQUEST:表示当前过滤其只会拦截普通请求,但是对forward和include的跳转不进行拦截。(默认值)

-  ERROR:表示当跳转到指定的错误处理页面时,这个跳转请求会被当前过滤器拦截。


-  <dispatcher>标签的ERROR取值示例:

-  在web.xml中填写如下代码,使得当跳转到指定的错误处理页面时,这个跳转请求会被当前过滤器拦截。

技术分享


5、多个Filter的执行顺序问题:

技术分享

-  当应用中存在多个Filter时,其执行顺序与注册顺序一致。(如上图所示,先执行OneFilter的请求过滤拦截,再是TwoFilter的请求过滤拦截,后是SomeServlet的执行,后是TwoFilter的响应过滤拦截,最后是TwoFilter的请求过滤拦截)


6、Filter的执行原理:

-  当某资源的请求到达Web容器时,会先对请求进行解析,使用解析出来的URI作为比较对象,从Map(Map的key为<url-pattern>的值,value为Filter实例对象的引用)中查找是否存在相匹配的key。若存在,那么读取其value,即Filter对象的引用,将该引用存入到数组中。然后继续向后查找,直到将该Map查找完毕。这样在数组中就存在按照查找顺序排好序的Filter引用。

-  数组初始化完毕后,开始按照数组元素顺序进行执行。所以数组中的Filter全部执行完毕之后,再跳转到请求的目标资源。(数组中存放着与请求相匹配的所有Filter)


7、附加说明:

a、若Filter为全路径匹配方式,那么url-pattern只能写为/*,而不能够写为/。(写为/,无论是静态资源,还是动态资源都不起作用)

-  <filter-mapping>标签中可以不使用<url-pattern>,但需要指定<servlet-name>,即当前过滤器拦截的是对指定Servlet的请求。


b、filter过滤器的应用:

-  可以在自定义的过滤器(MyCharactorEncodingFilter类)中解决POST提交中文乱码问题。

技术分享

本文出自 “12392717” 博客,请务必保留此出处http://12402717.blog.51cto.com/12392717/1977105

以上是关于Servlet编程专题9之Servlet规范中的过滤器的主要内容,如果未能解决你的问题,请参考以下文章

Servlet编程专题10之Servlet3.0注解

Servlet编程专题1之Servlet生命周期

Servlet编程专题4之Servlet核心

Servlet编程专题7之HttpSession

Servlet编程专题2之获取ServletConfig对象

Servlet编程专题3之url-pattern设置方式