Filter 可改变request,也可改变response

http://www.2cto.com/kf/201306/216264.html 

不可小觑的Filter 

java的过滤器Filter是个好东西,故名思议:用于过滤一些信息,过滤什么?什么时候过滤?怎么过滤? 




先理解一下Filter: 

Filter 不是一个servlet,它不能产生一个response,但是他能够在一个request到达servlet之前预先处理request,也可以在一个响应离开 servlet时处理response。故,用户可以使用filter改变一 个request或修改一个response。 




Filter的过滤: 

Filter和servlet的对应关系为多对多的关系 ,可以配置一个filter 到一个或多个servlet;而一个servlet可以有多个filter。 





什么时候过滤: 

编码转换: 

  Servlet过滤器在请求进入服务程序前都进行编码转换,解决跨平台的乱码问题。 


添加统一的标题或脚注: 


  统一风格。 

进行安全的控制: 

  用户辨认filter;日志filter;审核filter;加密filter;符号filter…… 

其他: 

  改变xml内容的XSLT filter。 




怎么过滤: 

实现过滤器API的3个接口:Filter 、Filter Chain 和 Filter Config。 

过滤器类将实现 Filter 接口,然后使用这个过滤器类中的 Filter Chain 和 Filter Config 接口。该过滤器类的一个引用将传递给 Filter Chain 对象,以允许过滤器把控制权传递给链中的下一个资源。Filter Config 对象将由容器提供给过滤器,以允许访问该过滤器的初始化数据。 


一般,filter都是一个链,在web.xml里配置,并且按照顺序执行,将请求转发给过滤链上的下一个对象,如果没有下一个filter链的节点,那就是你的请求资源。 





须理解的三个重要的方法:init()、doFilter ()、destroy() 

init():这个方法在容器实例化过滤器时被调用,它主要设计用于使过滤器为处理做准备。该方法接受一个 Filter Config 类型的对象作为输入。 
doFilter ():与 servlet 拥有一个 service() 方法(这个方法又调用 doPost() 或者 doGet())来处理请求一样,过滤器拥有单个用于处理请求和响应的方法——doFilter方法。这个方法接受三个输入参数:一个 Servlet Request、response 和一个 Filter Chain 对象。 
destroy():正如您想像的那样,这个方法执行任何清理操作,这些操作可能需要在自动垃圾收集之前进行。 





代码加深理解:过滤用户名和年龄的输入 

input.jsp过滤器检测姓名和年龄,正常的话,提交给output.jsp,如果异常,提交给erroroutput.jsp,同时还有一个过滤器,用来检测一个页面是否设置了字符编码,如果没有则进行设置(防止乱码)。 




myfilter.java: 



[java]  package servletbean; 
import javax.swing.JOptionPane; 
public class myfilter implements Filter{ 

    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServeltExcepiton{ 
         
        response.setContentType("text/html"); 
        response.setCharacterEncoding("GB2312"); 
        PrintWriter out = response.getWriter(); 
        String name =""; 
        String age =""; 

        int age1; 
        name =request.getParameter("name"); 
        age = request.getParameter("age"); 
         
        RequestDispatcher dispatch = request.getRequestDispatcher("erroroutput.jsp"); 
         
        if(name ==null || name="" ||name =" " || age==null){ 
            JOptionPane.showMessageDialog(null,"用户名和年龄输入错误!"); 
            dispatch.forward(request,response); 
            return ; 

        }else{ 
            try{ 

                age1=Integer.parseInt(age); 
            }catch(Excepiton e){ 
                 
                //JOptionPane.showMessageDialog(null,"年龄必须为数字!");  
                dispatch.forward(request,response);//如果是错误页面就到erroroutput.jsp中  
                return ; 

            } 
        } 


        //正确的输入,chain会自动查找下一个链,但是下面没有了,所以,就会跳转页面了,action="output.jsp"  
        chain.doFilter(request,response);    
         

         
    } 



} 

package servletbean; 
import javax.swing.JOptionPane; 
public class myfilter implements Filter{ 

public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServeltExcepiton{ 
  
  response.setContentType("text/html"); 
  response.setCharacterEncoding("GB2312"); 
  PrintWriter out = response.getWriter(); 
  String name =""; 
  String age =""; 

  int age1; 
  name =request.getParameter("name"); 
  age = request.getParameter("age"); 
  
  RequestDispatcher dispatch = request.getRequestDispatcher("erroroutput.jsp"); 
  
  if(name ==null || name="" ||name =" " || age==null){ 
   JOptionPane.showMessageDialog(null,"用户名和年龄输入错误!"); 
   dispatch.forward(request,response); 
   return ; 

  }else{ 
   try{ 

    age1=Integer.parseInt(age); 
   }catch(Excepiton e){ 
    
    //JOptionPane.showMessageDialog(null,"年龄必须为数字!"); 
    dispatch.forward(request,response);//如果是错误页面就到erroroutput.jsp中 
    return ; 

   } 
  } 


  //正确的输入,chain会自动查找下一个链,但是下面没有了,所以,就会跳转页面了,action="output.jsp" 
  chain.doFilter(request,response); 
  

  
} 



} 

encodefilter.java: 



[java] package servletbean; 
public class encodefilter implements Filter{ 

    public void doFilter (ServletRequest request, ServletResponse response,FilterChain chain ) throws IOException ,ServletException{ 
         
        if (request.getCharacterEncoding()==null){ 

            System.out.println(encoding); 
            request.setCharacterEncoding(encoding); 
        } 

        //到下一个链  
        chain.doFilter(request,response); 
    } 



    public void init(FilterConfig fConfig)   throws SevletException { 

        this.config=fConfig; 
        encoding =fConfig.getInitParameter("encoding"); 
         
    } 
} 

package servletbean; 
public class encodefilter implements Filter{ 

public void doFilter (ServletRequest request, ServletResponse response,FilterChain chain ) throws IOException ,ServletException{ 
  
  if (request.getCharacterEncoding()==null){ 

   System.out.println(encoding); 
   request.setCharacterEncoding(encoding); 
  } 

  //到下一个链 
  chain.doFilter(request,response); 
} 



public void init(FilterConfig fConfig)  throws SevletException { 

  this.config=fConfig; 
  encoding =fConfig.getInitParameter("encoding"); 
  
} 
} 

input.jsp: 



[java <form action ="output.jsp" name ="form" method ="post"> 

    <table> 
        <tr> 
            <td>name</td> 
            <td><input type="text" name ="name"></td>      
        </tr> 
        <tr> 
            <td>age</td>             
            <td><input type="text" name ="age"></td> 
        </tr> 
        <tr> 
            <td><input type ="submit" name="ok" value ="ok"></td> 
        </tr> 
    </talbe> 
</form> 

<form action ="output.jsp" name ="form" method ="post"> 

<table> 
  <tr> 
   <td>name</td> 
   <td><input type="text" name ="name"></td>  
  </tr> 
  <tr> 
   <td>age</td>   
   <td><input type="text" name ="age"></td> 
  </tr> 
  <tr> 
   <td><input type ="submit" name="ok" value ="ok"></td> 
  </tr> 
</talbe> 
</form> 

web.xml:filter是有顺序的。 



[java]  <filter> 

    <decsription> 
         
    </decsription> 

    <display-name>encodefilter</display-name> 
    <filter-name>encodefilter</filter-name> 
    <filter-class>servletbean.encodefilter</filter-class> 
    <init-param>   
        <param-name>encoding</param-name> 
        <param-value>GB2312</param-value>        
    </init-param> 
</filter> 

<filter-mapping> 
    <filter-name>encodefilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 






<filter> 
    <decsription> 
         
    </decsription> 

    <display-name>myfilter</display-name> 
    <filter-name>myfilter</filter-name> 
    <filter-class>servletbean.myfilter</filter-class> 
    <init-param>   
        <param-name>encoding</param-name> 
        <param-value>GB2312</param-value>        
    </init-param> 
</filter> 

<filter-mapping> 
    <filter-name>myfilter</filter-name> 
    <url-pattern>/output.jsp</url-pattern> 
</filter-mapping> 

<filter> 

<decsription> 
  
</decsription> 

<display-name>encodefilter</display-name> 
<filter-name>encodefilter</filter-name> 
<filter-class>servletbean.encodefilter</filter-class> 
<init-param> 
  <param-name>encoding</param-name> 
  <param-value>GB2312</param-value>  
</init-param> 
</filter> 

<filter-mapping> 
<filter-name>encodefilter</filter-name> 
<url-pattern>/*</url-pattern> 
</filter-mapping> 






<filter> 
<decsription> 
  
</decsription> 

<display-name>myfilter</display-name> 
<filter-name>myfilter</filter-name> 
<filter-class>servletbean.myfilter</filter-class> 
<init-param> 
  <param-name>encoding</param-name> 
  <param-value>GB2312</param-value>  
</init-param> 
</filter> 

<filter-mapping> 
<filter-name>myfilter</filter-name> 
<url-pattern>/output.jsp</url-pattern> 
</filter-mapping> 
一点儿小结: 

  过滤器可以在请求到达JSP或Servlet之前或响应返回客户端之前添加一些额外的操作。 
如果有多个JSP页面和Servlet都需要进行一个相同或相似的操作,我们可以把这个操作抽取到一个Servlet过滤器中,并通过匹配路径截获感兴趣JSP或Servlet。
 

====================================================================== 

http://blog.csdn.net/huangcongjie/article/details/7377422 

chain.doFilter(request,response)含义 

过滤器的生命周期一般都要经过下面三个阶段: 




初始化 

当容器第一次加载该过滤器时,init() 方法将被调用。该类在这个方法中包含了一个指向 Filter Config 对象的引用。我们的过滤器实际上并不需要这样做,因为其中没有使用初始化信息,这里只是出于演示的目的。 




过滤 

过滤器的大多数时间都消耗在这里。doFilter方法被容器调用,同时传入分别指向这个请求/响应链中的 Servlet Request、Servlet Response 和 Filter Chain 对象的引用。然后过滤器就有机会处理请求,将处理任务传递给链中的下一个资源(通过调用 Filter Chain 对象引用上的 doFilter方法),之后在处理控制权返回该过滤器时处理响应。 




析构 

容器紧跟在垃圾收集之前调用 destroy()方法,以便能够执行任何必需的清理代码。 




关于chain.doFilter(request,response) 
他的作用是将请求转发给过滤器链上下一个对象。这里的下一个指的是下一个filter,如果没有filter那就是你请求的资源。 一般filter都是一个链,web.xml 里面配置了几个就有几个。一个一个的连在一起 

request -> filter1 -> filter2 ->filter3 -> .... -> request resource.

猜你喜欢

转载自ap0406708.iteye.com/blog/1900929
今日推荐