filter過濾器
從J2EE1.3開始,Servlet2.3規范中加入了對過濾器的支持。過濾器能夠對目標資源的請求和響應進行截取。
Servlet2.4版本的servlet規范在部屬描述符中新增加了一個<dispatcher>元素,這個元素有四個可能的值:即REQUEST, FORWARD,INCLUDE和ERROR,可以在一個<filter-mapping>元素中加入任意數目的< dispatcher>,使得filter將會作用于直接從客戶端過來的request,通過forward過來的request,通過 include過來的request和通過<error-page>過來的request。如果沒有指定任何< dispatcher >元素,默認值是REQUEST。
過濾器的工作方式分為四種,下面讓我們分別來看看這四種過濾器的工作方式:
1、request過濾器
這種過濾器的工作方式比較簡單,大家也經常遇到,如下圖所示:

以下是web.xml文件配置方式:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>xx.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源一</servlet-name>
</filter-mapping>
下面我們更改一下web.xml文件的配置,如下方式:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>xx.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源一</servlet-name>
</filter-mapping>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源二</servlet-name>
</filter-mapping>
也就是說此過濾器對目標資源一和目標資源二都進行過濾,然后當目標資源一被訪問的時候我們將請求轉發給目標資源二,那么這個時候過濾器是怎么工作的呢?如下圖所示:

我們可以看到,當我們訪問目標資源一時過濾器截取了請求,然后再轉發給目標資源一,然后再轉發給目標資源二,從圖中我們可以看到過濾器沒有截取轉發到目標資源二的請求,但是我們已經在web.xml文件中配置了該過濾器對目標資源二的過濾,為什么又沒有起到過濾作用呢?
答案就在于,目標資源一是客戶端直接訪問,而目標資源二是被轉發過來的,這時過濾器就不能過濾目標資源二。如果你直接訪問目標資源二,你會發現該過濾器起到了作用?
我們上面的web.xml文件配置與以下方式等價:
<filter>myFilter</filter>
<filter-name>myFilter</filter-name>
<filter-class>xx.MyFilter</filte-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源一</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源二</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
這種方式的配置,說明只有直接訪問該目標資源時該過濾器才會起作用,對轉發到該目標資源的請求將忽略不處理。
那如果我想對轉發到目標資源二的請求進行過濾,那怎么辦呢?答案見,下一種過濾器,forward過濾器。
2、forward過濾器
我們將web.xml文件的配置修改如下:
<filter>myFilter</filter>
<filter-name>myFilter</filter-name>
<filter-class>xx.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源一</servlet-name>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源二</servlet-name>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
工作方式如下圖所示:

我們看對目標資源二過濾的配置方式,這時過濾方式為forward,也就是說對轉發到目標資源二的請求過濾,如果直接訪問目標資源二,過濾器將不起作用。
3、include過濾器
理解了forward過濾器之后,include過濾器就不難理解了。以下方式:
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>目標資源二</servlet-name>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
此表示對包含了目標資源二的請求過濾,如果直接訪問目標資源二,則此過濾器將不起作用。
include包含以下語句:
在JSP頁面中的動作:<jsp:include page=.......
在Java代碼中的request.getRequestDispatcher("....").include
注意:如果目標資源一通過<%@ include file="目標資源二"%>指令包含,這時此過濾器不工作。后面給大家介紹指令包含和動作包含的區別。
4、error過濾器
當我們訪問一個web目標資源時,如果服務器沒有找到該目標資源,那么服務器就會給出一個404錯誤代碼。如果我們給404錯誤代碼定義一個頁面,那么當404錯誤發生時就會調用該頁面,請看以下web.xml文件的配置:
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/error.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
當我們訪問一個不存在的文件時,就會訪問error.jsp,但是配置了過濾器對錯誤頁面進行過濾,所以過濾器先接受到請求,然后再轉發給error.jsp。
如果我們訪問一個已經存在的頁面,會不會調用error.jsp呢?如果這個頁面中有response.sendError(404,"出錯了!");那么該錯誤頁面仍然會被調用,過濾器也會工作.
filter-mapping元素用來聲明Web應用中的過濾器映射。過濾器可被映射到一個servlet或一個URL模式。將過濾器映射到一個 servlet中會造成過濾器作用于servlet上。將過濾器映射到一個URL模式中則可以將過濾器應用于任何資源,只要該資源的URL與URL模式匹 配。過濾是按照部署描述符的filter-mapping元素出現的順序執行的。
<!ELEMENT filter-mapping (filter-name, (url-pattern | servlet-name))>
<!ELEMENT filter-name (#PCDATA)>
<!ELEMENT url-pattern (#PCDATA)>
<!ELEMENT servlet-name (#PCDATA)>
filter-name值必須對應filter元素中聲明的其中一個過濾器名稱。下面是一個含有filter-mapping元素的部署描述符:
<?xml version="1.0" encoding="ISO-8859-1">
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>Encryption Filter</filter-name>
<filter-class>com.brainysoftware.EncryptionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>Encryption Filter</filter-name>
<servlet-name>EncryptionFilteredServlet</servlet-name>
</filter-mapping>
</web-app>
Example:
...
6 <filter>
7 <filter-name>helloWorld</filter-name>
8 <filter-class>com.acme.filter.HelloWorldFilter</filter-class>
9 </filter>
10 <filter>
11 <filter-name>message</filter-name>
12 <filter-class>com.acme.filter.MessageFilter</filter-class>
13 <init-param>
14 <param-name>message</param-name>
15 <param-value>A message to you!</param-value>
16 </init-param>
17 </filter>
18 <filter>
19 <filter-name>prePost</filter-name>
20 <filter-class>com.acme.filter.PrePostFilter</filter-class>
21 </filter>
22 <filter>
23 <filter-name>imageManipulator</filter-name>
24 <display-name>imageManipulator</display-name>
25 <filter-class>com.acme.filter.ImageFilter</filter-class>
26 <init-param>
27 <param-name>message</param-name>
28 <param-value>test</param-value>
29 </init-param>
30 </filter>
31 <filter>
32 <filter-name>gzip</filter-name>
33 <filter-class>com.acme.filter.GZIPFilter</filter-class>
34 </filter>
35 <filter-mapping>
36 <filter-name>helloWorld</filter-name>
37 <url-pattern>/filter.jsp</url-pattern>
38 </filter-mapping>
39 <filter-mapping>
40 <filter-name>message</filter-name>
41 <url-pattern>/filter2.jsp</url-pattern>
42 </filter-mapping>
43 <filter-mapping>
44 <filter-name>prePost</filter-name>
45 <url-pattern>/filter3.jsp</url-pattern>
46 </filter-mapping>
47 <filter-mapping>
48 <filter-name>imageManipulator</filter-name>
49 <url-pattern>/*.jpg</url-pattern>
50 </filter-mapping>
51 <filter-mapping>
52 <filter-name>gzip</filter-name>
53 <url-pattern>/*.jsp</url-pattern>
54 </filter-mapping>
posted on 2008-05-27 00:42 gembin 閱讀(1937) 評論(1) 編輯 收藏 所屬分類: JavaEE