ITEEDU

JSP/Servlet: Filter(1)

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

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

FilterDemo2.jav

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