Filter原理及应用
- filter功能
使用户可以改变一个request和修改一个response。Filter不是一个servlet,他不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开servlet时处理response。换种说法,filter其实是一个servlet chaining(servlet链)。
一个filter包括:
1、 在servlet被调用之前截获
2、 在servlet被调用之前检查servlet request。
3、 根据需要修改request头和request数据
4、 根据需要修改response头和response数据
5、 在servlet被调用之后截获。
你能够配置一个filter到一个或多个servlet;单个servlet或servlet组能够被多个filter使用。几个实用的filter包括:权限控制(可以防止URL跳转),Session控制,Web Cache(如比较大的图片加载时),用户辨认filter,日志filter,审核filter,加密filter,符号filter,能改变xml内容的XSLT filter等
- filter原理
当客户端发出web资源的请求时,web服务器根据应用程序配置文件设置的过滤规则进行检查,若客户请求满足过滤规则,则对客户请求/响应进行拦截,对请求头和请求数据进行检查或改动,并依次通过过滤器链,最后把请求/响应交给请求的web资源处理。请求信息在过滤器链中可以被修改,也可以根据条件让请求不发往资源处理器,并直接向客户机发回一个响应。当资源处理器完成了对资源的处理后,响应信息将逐级逆向返回。同样,这个过成功,用户可以修改相应信息,从而完成一定的任务。
当一个请求符合多个过滤器的过滤条件时,服务器会按照web.xml中过滤器定义的先后循环组装成一条链,然后依次执行其中的doFilter()方法。执行顺序为:执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilter()之后的代码,最后返回响应。如图
- filter注意事项:
filter技术在servlet2.3规范中加入的,大部分的jsp/servlet容器都支持
filter和ADP(Aspect Oriented Programming)面向切面的编程
Filter可以看做是一种横切的技术
Filter体现了一个模式,责任链模式
Servlet体现了一个模式模板方法模式
Java IO体现了装饰模式
Filter其实提供了一种声明式服务,声明式服务非常强大,它具有可插拔的能力
Filter其实对Request和Response请求进行了 拦截
Filter只对Post请求起作用
- filter实现
所有的过滤器都必须实现Filter接口。该接口定义了init,doFilter(),destroy()三个方法。
(1) public void init (FilterConfig filterConfig) throws ServletException.
当开始使用servlet过滤器服务时,Web容器调用此方法一次,为服务准备过滤器;然后在需要使用过滤器的时候调用doFilter(),传送给此方法的FilterConfig对象,包含servlet过滤器的初始化参数。
(2)public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
throws java.io.IOException,ServletException.
每个过滤器都接受当前的请求和响应,且FilterChain过滤器链中的过滤器(应该都是符合条件的)都会被执行。doFilter方 法中,过滤器可以对请求和响应做它想做的一切,通过调用他们的方法收集数据,或者给对象添加新的行为。过滤器通过传送至 此方法的FilterChain参数,调用chain.doFilterO将控制权传送给下一个过滤器。当这个调用返回后,过滤器可以在它的 Filter方法的最后对响应做些其他的工作。如果过滤器想要终止请求的处理或得到对响应的完全控制,则可以不调用下一个过滤
器,而将其重定向至其它一些页面。当链中的最后一个过滤器调用chain.doFilterO方法时,将运行最初请求的Servlet。
(3)public void destroy()
一旦doFilterO方法里的所有线程退出或已超时,容器调用此方法。服务器调用destoryO以指出过滤器已结束服务,用于释放过滤器占用的资源。
- 代码示例
//设置统一的字符集编码控制类 public class CharsetEncodingFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //设置字符集 System.out.println("begin"); request.setCharacterEncoding("GB18030"); //继续执行 chain.doFilter(request, response); System.out.println("end"); } public void init(FilterConfig filterConfig) throws ServletException { } }
配置文件
<filter> <filter-name>CharsetEncodingFilter</filter-name> <filter-class>kane.CharsetEncodingFilter</filter-class> <init-param> <param-name>charEncode</param-name> <param-value>GB18030</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharsetEncodingFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping>