Filter的执行顺序

Filter有如下几个用处。

  • 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest
  • 根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
  • 在HttpServletResponse到达客户端之前,拦截HttpServletResponse
  • 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。

首先,要知道在web.xml中,<url-pattern>指定了filter要进行拦截url范围,<url-pattern>/*</url-pattern>则表示拦截你%web-root%下对所有url的request和response

其次,Filter.doFilter()之中的代码,按执行顺序分成了3部分,1、在chain.doFilter()执行之前的代码,是用于处理request对象的,2、chain.doFilter(),3、chain.doFilter()之后的代码是用来处理response对象的

这里我们做2个filter,如下

FirstFilter

package org.lxh.filterdemo;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class FirstFilter implements Filter { 
    @Override  
    public void destroy() {   

    }   

    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,   
            FilterChain chain) throws IOException, ServletException {   
        System.out.println("before invoke firstFilter's chain.doFilter() ..");   
        chain.doFilter(request, response);   
        System.out.println("after invoke firstFilter's chain.doFilter() ..");   
    }

    @Override  
    public void init(FilterConfig arg0) throws ServletException {   
        System.out.println("firstFilter init()..."); 
    }
}

SecondFilter

package org.lxh.filterdemo;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SecondFilter implements Filter { 
    @Override  
    public void destroy() {   

    }   

    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,   
            FilterChain chain) throws IOException, ServletException {   
        System.out.println("before invoke secondFilter's chain.doFilter() ..");   
        chain.doFilter(request, response);   
        System.out.println("after invoke secondFilter's chain.doFilter() ..");   
    }

    @Override  
    public void init(FilterConfig arg0) throws ServletException {   
        System.out.println("secondFilter init()..."); 
    }
}

web.xml,注意2个filter-mapping的先后顺序是:first在前,second在后

<!-- first & second filter -->
    <filter>   
        <filter-name>firstFilter</filter-name>   
        <filter-class>org.lxh.filterdemo.FirstFilter</filter-class>   
    </filter>   
    <filter-mapping>   
        <filter-name>firstFilter</filter-name>   
        <url-pattern>/*</url-pattern>   
    </filter-mapping>
    <filter>   
        <filter-name>secondFilter</filter-name>   
        <filter-class>org.lxh.filterdemo.SecondFilter</filter-class>   
    </filter>
    <filter-mapping>   
        <filter-name>secondFilter</filter-name>   
        <url-pattern>/*</url-pattern>   
    </filter-mapping>

访问http://127.0.0.1:8080/mldn/,运行结果如下

before invoke firstFilter's chain.doFilter() ..
before invoke secondFilter's chain.doFilter() ..
after invoke secondFilter's chain.doFilter() ..
after invoke firstFilter's chain.doFilter() ..

上面的运行结果说明,执行流程是这样的:

... 客户端请求...  

       进入firstFilter.doFilter() 

                  System.out.println("before invoke firstFilter's chain.doFilter() ..")

                  chain.doFilter(request, response)

            进入secondFilter.doFilter()

                       System.out.println("before invoke secondFilter's chain.doFilter() ..")

                       chain.doFilter(request, response)

                   执行处理页面的servlet代码

                                          .. servlet代码执行完毕...返回

                       System.out.println("after invoke secondFilter's chain.doFilter() ..")

                         执行完毕,返回

      System.out.println("after invoke secondFilter's chain.doFilter() ..")

      执行完毕,返回

客户端接收响应

用图来表示的话,就可以用下面的图来表示,可见,中间两个大框从左到右就依次表示的是first.doFilter和second.doFilter,code1和code2分别表示chain.doFilter之前的print和chain.doFilter之后的print

好的,现在把web.xml改为如下,但是这次,注意,2个filter-mapping的先后顺序是:second在前,first在后

    <filter>   
        <filter-name>secondFilter</filter-name>   
        <filter-class>org.lxh.filterdemo.SecondFilter</filter-class>   
    </filter>
    <filter-mapping>   
        <filter-name>secondFilter</filter-name>   
        <url-pattern>/*</url-pattern>   
    </filter-mapping>
    <filter>   
        <filter-name>firstFilter</filter-name>   
        <filter-class>org.lxh.filterdemo.FirstFilter</filter-class>   
    </filter>   
    <filter-mapping>   
        <filter-name>firstFilter</filter-name>   
        <url-pattern>/*</url-pattern>   
    </filter-mapping>

执行结果如下:

before invoke secondFilter's chain.doFilter() ..

before invoke firstFilter's chain.doFilter() ..

after invoke firstFilter's chain.doFilter() ..

after invoke secondFilter's chain.doFilter() ..

显然,这次是secondFilter.doFilter()先执行,所以,多个filter.doFilter()的执行先后顺序与web.xml中对应的filter-mapping的先后顺序一致!

原文地址:https://www.cnblogs.com/qrlozte/p/3178651.html