Tomcat 7源码学习笔记 -8 Filter过滤器解读
1.过滤器的主要功能是允许我们在request转给某个资源之前(比如:html文件,servlet,JSP文件,图片文件,excel文件等等)做一些事情,然后在response返回给客户端之前做一些事情。功能上有些类似于防火墙,对入口和出口进行严格控制。
public class MyFilter implements Filter { //tomcat启动,或者context重新加载的时候调用init(先destroy再init) public void init(FilterConfig filterConfig) throws ServletException { System.out.println("MyFilter init..."); } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //request到达的时候执行下面的代码 System.out.println("MyFilter request>>>>>>>>>>>>"); //转给过滤器链中的下一个filter,如果是最后一个filter,调用要访问的资源 chain.doFilter(request,response); //要访问的资源访问完以后,response到达的时候执行下面的代码 System.out.println("MyFilter response>>>>>>>>>>>>"); } //tomcat关闭或者context重新加载的时候调用destroy public void destroy() { System.out.println("MyFilter destroy..."); } }
2.filter的配置方法
web.xml
通过url匹配:
<filter> <filter-name>My Filter</filter-name> <filter-class>MyFilter</filter-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> </filter> <filter-mapping> <filter-name>My Filter</filter-name> <!-- url匹配规则 --> <url-pattern>/*</url-pattern> <!-- filter对应的请求方式,默认是REQUEST --> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
通过servlet名匹配:
<filter> <filter-name>My Filter</filter-name> <filter-class>MyFilter</filter-class> <init-param> <param-name>debug</param-name> <param-value>0</param-value> </init-param> </filter> <filter-mapping> <filter-name>My Filter</filter-name> <!-- 根据url匹配到MyServlet的时候,执行My Filter --> <servlet-name>MyServlet</servlet-name> <!-- filter对应的请求方式,默认是REQUEST --> <dispatcher>REQUEST</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
3.过滤器链
1)request到达以后,实际匹配到的过滤器可能有一个,也可能有多个,多个的时候,会形成一个过滤器链,过滤器的执行顺序和web.xml中filter-mapping的配置的先后顺序一致,写在前面的先执行,写在后面的后执行。
2)每个过滤器执行完以后会调用chain.doFilter(request,response);从而调用下一个过滤器的doFilter方法。(其实此时执行到的只是每个过滤器中chain.doFilter(request,response);之前的代码)
3)当所有的匹配到的过滤器都执行完以后,将调用具体访问的资源,比如servlet,或者jsp。
4)请求的资源执行结束后,response返回的时候,再次调用匹配到的过滤器。调用顺序和request到达时的调用顺序正好相反。(此时执行的是每个过滤器中chain.doFilter(request,response);之后的代码)
如果在过滤器的doFilter前后,以及访问的servlet的doGet中事先写入打印调试信息的话,在浏览器中提交某个get请求的话,在控制台会看到下面的打印信息:
MyFilter1request>>>>>>>>>>>>
MyFilter2request>>>>>>>>>>>>
MyFilter3request>>>>>>>>>>>>
MyServletdoGet>>>>>>>>>>>>
MyFilter3response>>>>>>>>>>>>
MyFilter2response>>>>>>>>>>>>
MyFilter1response>>>>>>>>>>>>
对应的调用顺序如下:
客户端发出request-->MyFilter1-->MyFilter2-->MyFilter3-->MyServlet-->MyFilter3-->MyFilter2-->MyFilter1
-->客户端获得response