jsp/servlet过滤器--Filter

Filter可以担任浏览器与JSP/Servlet之间的一个中介处理者,一些request的前置处理动作及一些response的后置处理,都可以交由这个中介处理者来完成,当然Filter可以达到的功能,您也可以直接撰写在JSP/Servlet中,但如果有很多JSP/Servlet都需要相同的处理,例如某些网页都需要统一的身份验证方式时,与其在每一个网页中都撰写验证的程序码,不如直接撰写Filter,让它来统一进行处理。

Filter实际上是一个纯綷的Java类程序,它要实现javax.servlet.Filter接 口,这个接口中有三个必须实现的方法:init()、destory()与doFilter()。init()是Filter类被载入时会执行的方法,而destory()是 Filter对象生命周期结束时会执行的方,至于doFilter()则是实现Filter功能的核心,您想要Filter完成的工作就撰写在其中,先来撰写一个简单的Filter类,如下:

  • FilterDemo1.java
package onlyfun.caterpillar; import java.io.*;
 import javax.servlet.*;
  import javax.servlet.http.*;  
  public class FilterDemo1 implements Filter {     
  		public void init(FilterConfig config) throws ServletException { }      
  		public void destroy() { }      
  		public void doFilter(ServletRequest request,ServletResponse response,             FilterChain chain) throws IOException, ServletException {        
  		 		PrintWriter out = response.getWriter();         
  		 		out.println("Filter 1 is doing!!!");          
  		 		chain.doFilter(request, response);          
  		 		out.println("Filter 1's work is done");     
  		 		}
  		 } 

在这个程序中,只是简单的显示一些文字,表示Filter的doFilter()方法有被执行,doFilter()传入三个参数, ServletRequest、ServletResponse、FilterChain,您可以获得request与response对象,以对它们进行一些处理,像是设定标头、编码格式或包装压缩功能等等,至于FilterChain则是关于Filter执行顺序的对象,这个顺序是设定在 web.xml中,您必须调用它的doFilter()方法,才可以执行下一个Filter,如果是最后一个Filter,则执行客户端所请求的 JSP/Servlet网页。

为了要能使用Filter,您必须在web.xml中撰写一些设定,一个设定范例如下:

  • web.xml
<filter>         
	<filter-name>FilterDemo1</filter-name>        
 	<filter-class>onlyfun.caterpillar.FilterDemo1</filter-class>     
 </filter>     
 <filter-mapping>         
 	<filter-name>FilterDemo1</filter-name>         
 	<url-pattern>/*</url-pattern>     
 </filter-mapping> 

与之间撰写Filter的名称与实际载入的类,Filter类档是放置在WEB- INF/classes/下,而与</filter- mapping>之间则撰写Filter名称与所要过滤的资源对象,在这边设定为/*,表示请求这个Web应用程序下的所有资源,都要先经过 Filter的处理。

如果设定的套用了两个Filter,则FilterChain在执行doFilter()方法时,其调用的 Filter顺序就是您在web.xml中撰写Filter的顺序,例如再撰写一个Filter程序:

  • FilterDemo2.java
package onlyfun.caterpillar; import java.io.*;
 import javax.servlet.*;
  import javax.servlet.http.*;  
  public class FilterDemo2 implements Filter {     
  		public void init(FilterConfig config)  throws ServletException {}  
  		public void destroy() {}      
  		public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)  throws IOException, ServletException { 
  		        PrintWriter out = response.getWriter();       
  		        out.println("Filter 2 is doing!!!");          
  		        chain.doFilter(request, response);          
  		        out.println("Filter 2's work is done");     
  		        } 
  		   }

web.xml中设定的内容是:

  • web.xml
<filter>
         <filter-name>FilterDemo1</filter-name>         
         <filter-class>onlyfun.caterpillar.FilterDemo1</filter-class>     
</filter>     
<filter-mapping>
         <filter-name>FilterDemo1</filter-name>         
         <url-pattern>/*</url-pattern>     
</filter-mapping>     
<filter>
         <filter-name>FilterDemo2</filter-name>         
         <filter-class>onlyfun.caterpillar.FilterDemo2</filter-class>     
</filter>
<filter-mapping>         
     <filter-name>FilterDemo2</filter-name>         
     <url-pattern>/*</url-pattern>     
</filter-mapping> 

则请求Web应用程序下的任一个资源,都会先执行FilterDemo1,然后再执行FilterDemo2,最后调用请求的资源,如果请求的资源是 JSP网页,而它的功能只是印出 5 个Hello! World!:

  • test.jsp
<%     for(int i = 0; i < 5; i++)         out.println("Hello! World!"); %> 

则调用该JSP网页时,所得到的结果是:

Filter 1 is doing!!! 
Filter 2 is doing!!! 
Hello! World! 
Hello! World!
Hello! World!
Hello! World!
Hello! World!
Filter 2's work is done
Filter 1's work is done  

在实现Filter接口时必须实现init()方法,该方法传入一个FilterConfig对象作为参数,它包括了一些容器传递给Filter,有关于Filter的相关设定信息,您可以透过下面几个方法来取得这些信息:

public java.lang.String getFilterName() 
public java.lang.String getInitParameter(java.lang.String name) 
public java.util.Enumeration getInitParameterNames() 
public ServletContext getServletContext() 

其中getInitParameter()与getInitParameterNames()信息的取得来源,即web.xml中设定的参数讯息,使用方法与之前设定Servlet时相同,一个例子如下:

  • web.xml
 <filter>
     <filter-name>SomeFilter</filter-name>    
     <filter-class>onlyfun.caterpillar.SomeFilter</filter-class>    
     <init-param> 
            <param-name>parameter1</param-name>        
            <param-value>paramValue</param-value>    
      </init-param>  
</filter> 

在Servlet 2.3之前,Filter的触发只能透过使用者的直接请求,而在Servlet 2.4之后,您可以透过几个可能的转发或包括等方式来触发Filter,这可以在web.xml中加以设定,触发Filter的方式有FORWARD、 INCLUDE、REQUEST与ERROR,即转发、包含、请求与错误网页请求时,默认的触发方式是REQUEST,您可以使用< dispatcher>标签来加以设定,例如:

  • web.xml
<filter-mapping>
    <filter-name>SomeFilter</filter-name>    
    <url-pattern>/somePage.jsp</url-mapping>    		
    <dispatcher>REQUEST</dispatcher>    
    <dispatcher>INCLUDE</dispatcher>  
</filter-mapping>

除了在doFilter()中撰写简单的过滤功能、添加request或response的信息之外,您也许还会想要直接的加强request与 response的处理方式,例如增加对请求资源的压缩功能,这种在原来的request与response功能之上,再添加额外的处理功能,可以采用 Decorator 模式,在Servlet 2.4之后,提供了实现装饰模式的Wrapper类:
ServletRequestWrapper、ServletResponseWrapper、 HttpServletRequestWrapper、HttpServletResponseWrapper,前两者分别实现了 ServletRequest与ServletResponse,后两者则分别又继承了前两者,您可以继承这些类,以装饰模式来添加request与 response的额外处理能力。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值