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


之前總是弄混這兩者,今天看了幾篇文章,小結一下在這里。

 

Filter介紹

      Filter可以認為是Servlet的一種“加強版”,它主要用於對用戶請求進行預處理,也可以對HttpServletResponse進行后處理,是個典型的處理鏈。Filter也可以對用戶請求生成響應,這一點與Servlet相同,但實際上很少會使用Filter向用戶請求生成響應。使用Filter完整的流程是:Filter對用戶請求進行預處理,接着將請求交給Servlet進行預處理並生成響應,最后Filter再對服務器響應進行后處理。

 

  Filter有如下幾個用處。

  • 在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,它是分散關注的編程方法,它將通用需求功能從不相關類之中分離出來;同時,能夠共享一個行為,一旦行為發生變化,不必修改很多類,只要修改這個行為就可以。

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

     當你提交對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的資源方便。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM