天天看點

Servlet的Filter的使用

    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>&lt;</code><code>filter</code><code>&gt;</code>

<code>  &lt;</code><code>filter-name</code><code>&gt;log&lt;/</code><code>filter-name</code><code>&gt; </code><code>&lt;!-- 此屬性相當于@webfilter中的filtername屬性 --&gt;</code>

<code>  &lt;</code><code>filter-class</code><code>&gt;com.abc.logfilter&lt;/</code><code>filter-class</code><code>&gt;  </code><code>&lt;!-- filter的實作類 --&gt;</code>

<code>  &lt;</code><code>init-param</code><code>&gt;</code>

<code>    &lt;</code><code>param-name</code><code>&gt;encoding&lt;/</code><code>param-name</code><code>&gt;</code>

<code>    &lt;</code><code>param-value</code><code>&gt;utf-8&lt;/</code><code>param-value</code><code>&gt;</code>

<code>  &lt;/</code><code>init-param</code><code>&gt;</code>

<code>    &lt;</code><code>param-name</code><code>&gt;loginpage&lt;/</code><code>param-name</code><code>&gt;</code>

<code>    &lt;</code><code>param-value</code><code>&gt;/login.jsp&lt;/</code><code>param-value</code><code>&gt;</code>

<code>&lt;/</code><code>filter</code><code>&gt;</code>

<code>&lt;</code><code>filter-mapping</code><code>&gt;</code>

<code>  &lt;</code><code>filter-name</code><code>&gt;log&lt;/</code><code>filter-name</code><code>&gt;</code>

<code>  &lt;</code><code>url-pattern</code><code>&gt;/*&lt;/</code><code>url-pattern</code><code>&gt; </code><code>&lt;!-- 負責攔截所有的url,相當于@webfilter中的urlpatterns屬性 --&gt;</code>

<code>&lt;/</code><code>filter-mapping</code><code>&gt;</code>