filter可認為是servlet的“加強版”,主要用于對使用者請求進行預處理,也可以對httpservletresponse進行後處理,是個典型的處理鍊。filter也可以對使用者請求生成相應,這一點與servlet相同,但實際上很少會這樣使用。使用filter的完整流程是:filter對使用者的請求進行預處理,接着将請求交給servlet進行處理并響應生成,最後filter在對伺服器響應進行後處理。
1. filter有如下幾個用處:
在httpservletrequest到達servlet之前,攔截客戶的httpservletrequest
根據需要,檢查httpservletrequest,也可以修改httpservletrequest的頭和資料
在httpservletresponse到達用戶端之前,攔截httpservletresponse
根據需要,檢查httpservletresponse,也可以修改httpservletresponse的頭和資料
2. filter有如下幾個種類:
使用者授權的filter:filter負責檢查使用者請求,根據請求過濾使用者的非法請求,通常用于權限管理。
日志filter:詳細記錄某些特殊的使用者請求
負責解碼的filter:包括對非标準編碼的請求解碼
能改變xml内容的xslt filter等
3. 建立一個filter隻需兩個步驟:
1). 建立filter處理類 2). 在web.xml檔案中配置filter
3.1 建立filter處理類
建立filter必須實作javax.servlet.filter接口,在該接口中定義了如下三個方法:
void init(filterconfig config):用于完成filter的初始化
void destroy():用于filter銷毀錢,完成某些資源的回收
void dofilter(servletrequest request, servletresponse response, filterchain chain):實作過濾功能,該方法就是對每個請求及響應增加的額外處理
下面是一個日志filter,它負責攔截所有的使用者請求,并将請求的資訊記錄在日志中。
<a href="http://my.oschina.net/itblog/blog/204725#">?</a>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<code>@webfilter</code><code>(filtername=</code><code>"log"</code><code>, urlpatterns={</code><code>"/*"</code><code>}, initparams={ </code><code>//這裡使用注解的方式配置filter</code>
<code> </code><code>@webinitparam</code><code>(name=</code><code>"encoding"</code> <code>value=</code><code>"utf-8"</code><code>),</code>
<code> </code><code>@webinitparam</code><code>(name=</code><code>"loginpage"</code> <code>value=</code><code>"/login.jsp"</code><code>)</code>
<code>}) </code>
<code>public</code> <code>class</code> <code>logfilter </code><code>implements</code> <code>filter {</code>
<code> </code><code>private</code> <code>filterconfig config;</code><code>//filterconfig可用于通路filter的配置資訊</code>
<code> </code><code>public</code> <code>void</code> <code>init(filterconfig config) { </code><code>this</code><code>.config = config; }</code>
<code> </code><code>public</code> <code>void</code> <code>destroy(){</code><code>this</code><code>.config = </code><code>null</code><code>;}</code>
<code> </code><code>public</code> <code>void</code> <code>dofilter(servletrequest req, servletresponse resp, filterchain chain) </code><code>throws</code> <code>ioexception, servletexception{</code>
<code> </code><code>//下面的代碼用于對使用者請求執行預處理</code>
<code> servletcontext context = </code><code>this</code><code>.config.getservletcontext();</code><code>//擷取servletcontext對象,用于記錄日志</code>
<code> </code><code>long</code> <code>before = system.currenttimemillis();</code>
<code> system.out.println(</code><code>"開始過濾..."</code><code>);</code>
<code> httpservletrequest request = (httpservletrequest)req;</code>
<code> system.out.println(</code><code>"已經攔截到使用者的請求位址:"</code> <code>+ request.getservletpath());</code>
<code> chain.dofilter(req, resp);</code><code>//filter隻是鍊式處理,請求依然放行到目的位址</code>
<code> </code>
<code> </code><code>//下面的代碼用于對伺服器響應執行後處理</code>
<code> </code><code>long</code> <code>after = system.currenttimemillis();</code>
<code> system.out.println(</code><code>"過濾結束"</code><code>);</code>
<code> system.out.println(</code><code>"請求被定位到:"</code> <code>+ request.getrequesturi() + </code><code>" 耗時:"</code> <code>+ (after - before));</code><code>//這裡隻是輸出提示資訊</code>
<code> }</code>
<code>}</code>
上面的代碼實作了dofilter()方法,實作該方法可以實作對使用者請求的預處理,也可實作對伺服器響應的後處理,它們的分界線為是否調用了chain.dofilter()方法,在這之前的是對使用者請求的預處理,在這之後的,是對伺服器響應的後處理。當filter對請求過濾後,依然将請求發送到目的位址。如果需要檢查權限,可以在filter中根據使用者請求的httpsession,判斷使用者權限是否足夠。如果權限不足,直接調用重定向即可,無需調用chain.dofilter()方法。
3.2 配置filter
filter在web.xml中的配置和servlet在web.xml中的配置很相似,差別在于:一個servlet通常隻配置一個url,而filter可以同時攔截多個請求的url,是以在配置filter的urlpatterns時,通常會使用模式字元串,使得filter可以攔截多個請求。和servlet相似的是,配置filter同樣有兩種方式:1). 在filter類中通過注解進行配置 2). 在web.xml檔案中進行配置
@webfilter支援的常用屬性介紹:
asyncsupported:指定該filter是否支援異步操作模式
dispatchertypes:指定該filter僅對那種dispatcher模式的請求進行過濾。該屬性支援async, error, forward, include, request這5個值的任意組合,預設值為同時過濾這5中模式的請求
displayname:指定該filter的顯示名
filtername:指定該filter的名稱
initparams:用于為該filter配置參數
servletnames:該屬性可以指定多個servlet名稱,用于指定該filter僅對這些servlet進行過濾
urlpatterns/value:這兩個屬性的作用完全相同,用于指定該filter所攔截的url
下面是一個在web.xml中配置filter的例子:
<code><</code><code>filter</code><code>></code>
<code> <</code><code>filter-name</code><code>>log</</code><code>filter-name</code><code>> </code><code><!-- 此屬性相當于@webfilter中的filtername屬性 --></code>
<code> <</code><code>filter-class</code><code>>com.abc.logfilter</</code><code>filter-class</code><code>> </code><code><!-- filter的實作類 --></code>
<code> <</code><code>init-param</code><code>></code>
<code> <</code><code>param-name</code><code>>encoding</</code><code>param-name</code><code>></code>
<code> <</code><code>param-value</code><code>>utf-8</</code><code>param-value</code><code>></code>
<code> </</code><code>init-param</code><code>></code>
<code> <</code><code>param-name</code><code>>loginpage</</code><code>param-name</code><code>></code>
<code> <</code><code>param-value</code><code>>/login.jsp</</code><code>param-value</code><code>></code>
<code></</code><code>filter</code><code>></code>
<code><</code><code>filter-mapping</code><code>></code>
<code> <</code><code>filter-name</code><code>>log</</code><code>filter-name</code><code>></code>
<code> <</code><code>url-pattern</code><code>>/*</</code><code>url-pattern</code><code>> </code><code><!-- 負責攔截所有的url,相當于@webfilter中的urlpatterns屬性 --></code>
<code></</code><code>filter-mapping</code><code>></code>