Servlet Filter(过滤器)是小型的web组件,它能够处理传入的请求和传出的响应。它能够在一个request到达Servlet之前预处理request,也可以在离开Servlet时处理response。它具有高度的透明性,无需更改应用程序代码,就可以根据需要添加、修改或从应用程序中将它删除。
一个Filter 包括:
- 在servlet被调用之前截获;
- 在servlet被调用之前检查servlet request;
- 根据需要修改request头和request数据;
- 根据需要修改response头和response数据;
- 在servlet被调用之后截获.
创建一个Filter我们只要implements Filter接口然后重写Filter接口中的三个方法就可以了,下面创建一个我们自己的Filter名字叫MyFilter:
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 MyFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("enter filter....");
chain.doFilter(request, response);
System.out.println("out filter....");
}
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
}
}
在创建完MyFilter类之后,需要在web.xml文件加入相应代码进行部署:
<filter> <display-name>MyFilter</display-name> <filter-name>MyFilter</filter-name> <filter-class>cookie.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
这样配置完之后,当我们再通过浏览器去访问的时候,所有的请求都会先经过MyFilter,首先执行doFilter方法中的System.out.println("enter filter...."); 然后执行chain.doFilter(request, response);如果还有其它的Filter则会继续调用其它的Filter,如果没有其它的Filter则调用所请求的Servlet,在调用完Servlet之后就执行System.out.println("out filter....");然后请求结束。
如果要建立多个Filter写法也和上面的一样创建另一个Filter类,在web.xml中进行部署。在这里如果项目中有多个Filter,它们的执行顺序是怎么区别的呢?通过测试发现,服务器会通过web.xml中Filter部署的顺序来决定每个Filter执行的顺序:
<filter> <display-name>MyFilter2</display-name> <filter-name>MyFilter2</filter-name> <filter-class>cookie.MyFilter2</filter-class> </filter> <filter-mapping> <filter-name>MyFilter2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <display-name>MyFilter</display-name> <filter-name>MyFilter</filter-name> <filter-class>cookie.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
上面有两个Filter,MyFilter和MyFilter2但MyFilter2在web.xml中是放在MyFilter的前面的,所以当执行的时候是会先执行MyFilter2。
通过源码可以看到FilterChain接口的实现类ApplicationFilterChain有个数组filters,这个里面放的就是我们所定义的所有Filter。当启动服务器的时候服务器通过web.xml所定义的<filter>标签中的内容去实例化每个过渡器,并把每个实例添加到filters这个数组中。
final class ApplicationFilterChain implements FilterChain, CometFilterChain{
private static final ThreadLocal lastServicedRequest;
private static final ThreadLocal lastServicedResponse;
public static final int INCREMENT = 10;
private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];