過濾器(Filter)和攔截器(Interceptor)

以前老是弄混這二者,今天看了幾篇文章,小結一下在這裏。java

 

Filter介紹

      Filter能夠認爲是Servlet的一種「增強版」,它主要用於對用戶請求進行預處理,也能夠對HttpServletResponse進行後處理,是個典型的處理鏈。Filter也能夠對用戶請求生成響應,這一點與Servlet相同,但實際上不多會使用Filter向用戶請求生成響應。使用Filter完整的流程是:Filter對用戶請求進行預處理,接着將請求交給Servlet進行預處理並生成響應,最後Filter再對服務器響應進行後處理。web

 

  Filter有以下幾個用處。spring

  • 在HttpServletRequest到達Servlet以前,攔截客戶的HttpServletRequest。
  • 根據須要檢查HttpServletRequest,也能夠修改HttpServletRequest頭和數據。
  • 在HttpServletResponse到達客戶端以前,攔截HttpServletResponse。
  • 根據須要檢查HttpServletResponse,也能夠修改HttpServletResponse頭和數據。

   Filter有以下幾個種類。編程

  • 用戶受權的Filter:Filter負責檢查用戶請求,根據請求過濾用戶非法請求。
  • 日誌Filter:詳細記錄某些特殊的用戶請求。
  • 負責解碼的Filter:包括對非標準編碼的請求解碼。
  • 能改變XML內容的XSLT Filter等。
  • Filter能夠負責攔截多個請求或響應;一個請求或響應也能夠被多個Filter攔截。

   建立一個Filter只需兩個步驟安全

  1. 建立Filter處理類
  2. web.xml文件中配置Filter

   建立Filter必須實現javax.servlet.Filter接口,在該接口中定義了以下三個方法。服務器

  • void init(FilterConfig config):用於完成Filter的初始化。
  • void destory():用於Filter銷燬前,完成某些資源的回收。
  • void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):實現過濾功能,該方法就是對每一個請求及響應增長的額外處理。該方法能夠實現對用戶請求進行預處理(ServletRequest request),也可實現對服務器響應進行後處理(ServletResponse response)—它們的分界線爲是否調用了chain.doFilter(),執行該方法以前,即對用戶請求進行預處理;執行該方法以後,即對服務器響應進行後處理。

 

Interceptor介紹

     攔截器,在AOP(Aspect-Oriented Programming)中用於在某個方法或字段被訪問以前,進行攔截,而後在以前或以後加入某些操做。攔截是AOP的一種實現策略。函數

     在WebWork的中文文檔的解釋爲—攔截器是動態攔截Action調用的對象。它提供了一種機制可使開發者能夠定義在一個Action執行的先後執行的代碼,也能夠在一個Action執行前阻止其執行。同時也提供了一種能夠提取Action中可重用的部分的方式。編碼

     攔截器將Action共用的行爲獨立出來,在Action執行先後執行。這也就是咱們所說的AOP,它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,可以共享一個行爲,一旦行爲發生變化,沒必要修改不少類,只要修改這個行爲就能夠。url

     攔截器將不少功能從咱們的Action中獨立出來,大量減小了咱們Action的代碼,獨立出來的行爲就有很好的重用性。spa

     當你提交對Action(默認是.action結尾的url)的請求時,ServletDispatcher會根據你的請求,去調度並執行相應的Action。在Action執行以前,調用被Interceptor截取,Interceptor在Action執行先後執行。

     建立Interceptor必須實現com.opensymphony.xwork2.interceptor.Interceptor接口,該接口定義了以下三個方法。

  • void init():在該攔截器被實例化以後,在該攔截器執行攔截以前,系統將回調該方法。對於每一個攔截器而言,其init()方法只執行一次。所以,該方法的方法體主要用於初始化資源。
  • void destory():該方法與init()方法對應。在攔截器實例被銷燬以前,系統將回調該攔截器的destory方法,該方法用於銷燬在init方法裏打開的資源。
  • String intercept(ActionInvocation invocation):該方法是用戶須要實現的攔截動做。就像Action的execute方法同樣。intercept方法會返回一個字符串做爲邏輯視圖。若是該方法直接返回了一個字符串,系統會將跳轉到該邏輯視圖對應的實際視圖資源,不會調用被攔截的Action。該方法的ActionInvocation參數包含了被攔截的Action的引用,能夠經過調用該參數的invoke方法,將控制權轉給下一個攔截器,或者轉給Action的execute方法(若是該攔截器後沒有其餘攔截器,則直接執行Action的execute方法)。

 

Filter和Interceptor的區別

  • Filter是基於函數回調(doFilter()方法)的,而Interceptor則是基於Java反射的(AOP思想)。
  • Filter依賴於Servlet容器,而Interceptor不依賴於Servlet容器。
  • Filter對幾乎全部的請求起做用,而Interceptor只能對action請求起做用。
  • Interceptor能夠訪問Action的上下文,值棧裏的對象,而Filter不能。
  • 在action的生命週期裏,Interceptor能夠被屢次調用,而Filter只能在容器初始化時調用一次。

Filter和Interceptor的執行順序

     過濾前-攔截前-action執行-攔截後-過濾後

 

一些理解:

但凡跟servlet有關——參數url-pattern指定的目標,均可以用filter。 
至於interceptor,一般的場景是利用反射來管理某個類的方法。好比但凡Service的save.*和delete.*的方法都必須開啓事務處理,全部Dao方法拋出異常時統一處理等。 
可是Action/controller比較特殊,由於它既是類的方法,又是映射到某個url上,容易讓人困惑。 

 
好比登錄校驗,沒有登錄的所有跳轉到一個錯誤頁面 
好比後臺安全校驗,安全校驗不經過的跳轉到一個錯誤頁面


其實兩種均可以, 

    • 用filter過濾url。拿原始的web資源比較方便。
    • 用interceptor過濾方法。拿request和response不必定方便,但訪問spring的資源方便。
相關文章
相關標籤/搜索