Filter介绍
Filter
Filter可以认为是Servlet的“加强版”,它主要用于对用户的请求进行预处理,也可以对Response进行后处理,是一个处理链
*一个Filter可以负责拦截多个请求、响应
一个请求、响应也可以被多个Filter拦截*
Filter的一些用处:
- 在HttpServletRequest到达Servlet之前,拦截请求,根据需要进行检查、或修改请求头和数据
- 在HttpServletResponse送往客户端前,拦截响应,根据需要进行检查、或修改响应头和数据
Filter常见的几个种类
- 用户授权的filter:负责检查用户请求,过滤非法请求
- 日志Filter:记录某些特殊的用户请求
- 负责解码的Filter:包括对非标准编码的请求解码
- 可以改变XML内容的XSLT Filter等
Filter实现
创建Filter类
创建Filter必须实现javax.servlet.Filter接口,该接口定义了三个方法:
- void init(FilterConfig config) :用于完成Filter的初始化操作
- void destroy() :Filter 对象销毁时调用此方法,用于回收一些资源
- void doFilter(ServletRequest request , ServletResponse resopnse , FilterChain chain) :实现过滤功能
以上只是对这三个方法的简单介绍,后面进行详细介绍
以简单的日志Filter举例,介绍Filter的创建
@WebFilter(filterName="log",urlPatterns={"/*"})
public class LogFilter implements Filter {
//用于访问Filter的配置信息
private FilterConfig config;
@Override
public void init(FilterConfig arg0) throws ServletException {
this.config=config;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
ServletContext context = this.config.getServletContext();
long before = System.currentTimeMillis();
HttpServletRequest hsrequest = (HttpServletRequest) request;
System.out.println("Filter拦截到的请求路径:"+hsrequest.getServletPath());
//Filter是链式处理,将请求转发到下一Filter或目的地址
chain.doFilter(request, response);
long after = System.currentTimeMillis();
System.out.println("请求定位到:"+hsrequest.getRequestURI()+" 所花费时长: "+ (after-before));
}
@Override
public void destroy() {
// TODO Auto-generated method stub
this.config= null;
}
}
配置Filter
(1) web.xml配置文件:
<filter>
<filter-name>log</filter-name>
<filter-class>lee.LogFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>log</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
(2)@WebFilter注解修饰Filter实现类
@WebFilter常用属性:
- asyncSupported : 指定该Filter是否支持异步操作模式
- displayName : 指定Filter的显示名
- filterName : 指定该filter的名称
- initParams : 为该Filter配置参数
- servletNames : 可指定多个Servlet名称,用于指定该Filter仅对这几个Servlet执行过滤
- urlPatterns / value : 这两个属性作用完全相同,指定该Filter所拦截过滤的url
Filter如何工作
Filter相关的类图
(1)FilterChain对象可以灵活地控制请求的流转
(2)在Tomcat容器中,FilterConfig和FilterChain的实现类分别是ApplicationFilterConfig和ApplicationFilterChain,Filter类由用户实现
(3)FilterChain是Filter的核心,FilterChain对象保存了直到最终的Servlet对象的所有Filter对象,这些对象都保存在ApplicationFilterChain对象的filters数组中。在FilterChain链上每执行一个Filter对象,数组的当前计数都会加 1,直到计数等于数组的长度,当FilterChain上所有的Filter对象执行完成后,就会执行最终的Servlet。所以ApplicationFilterChain对象中会持有Servlet对象的引用
(4)Filter接口定义的三个方法:
void init(FilterConfig config) : 初始化接口,在用户自定义的Filter初始化时被调用,它与Servlet的init方法作用一样,FilterConfig 与ServletConfig也类似,两者都能获取到容器的环境类ServletContext对象,FilterConfig的 getInitParameters()方法能获取在< filter >下配置的 < init-param >参数值
doFilter(ServletRequest request , ServletResponse resopnse , FilterChain chain) : 在每个用户的请求进来时,这个方法会被调用,并在Servlet的service方法之前被调用。而FilterChain就代表着当前的整个请求链,所以通过调用FilterChain.doFilter(request, response)可以将请求继续传递下去。如果想拦截这个请求,可以不调用FilterChain.doFilter(request, response),当前Filter类的doFilter(ServletRequest request , ServletResponse resopnse , FilterChain chain)方法执行结束后,则这个请求就直接返回。Filter链是递归执行的,且是一种责任链设计模式
void destroy() :Filter对象销毁时,此方法调用。注意:当Web容器调用这个方法后,容器会再调用一次doFilter方法
Filter执行顺序
ApplicationFilterChain类可以按照web.xml中Filter定义的先后顺序将多个Filter串联起来,组成一个链
Filter执行时序图
参考:
《轻量级Java EE 企业应用实践 –Struts2+Spring+Hibernate》
《深入分析Java Web 技术内幕》
http://docs.oracle.com/javaee/6/api/