1. 程式人生 > >過濾器(Filter)與攔截器

過濾器(Filter)與攔截器

1. 過濾器(Filter)

依賴於servlet容器。在實現上基於函式回撥,可以對幾乎所有請求進行過濾,但是缺點是一個過濾器例項只能在容器初始化時呼叫一次。使用過濾器的目的是用來做一些過濾操作,獲取我們想要獲取的資料,比如:在過濾器中修改字元編碼;在過濾器中修改HttpServletRequest的一些引數,包括:過濾低俗文字、危險字元等

1.1 作用

首先對使用者的請求進行預處理,緊接著將請求交給servlet進行處理並相應,最後filter在對伺服器響應進行後處理。

1.2 應用案例

對使用者的請求設定編碼字符集,非法請求,許可權設定,是否登入等操作。

1.3 使用方法

1.在web.xml進行配置;

2.自定義自己的filter實現類,重寫有三個方法:

  • Init():實現初始化方法;

  • Dofilter():執行過濾的核心方法;

  • Destroy():執行銷燬方法。

多個匹配的Filter,是按照其在web.xml中配置的順序來執行的

2. 攔截器

2.1簡介

攔截器是AOP實現的一種策略,在AOP中用於在訪問某個方法或欄位之前,進行攔截,在執行之前或之後加入某些處理。

SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的。在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式,第一種方式是要定義的Interceptor類要實現了Spring 的HandlerInterceptor 介面,或者是這個類繼承實現了HandlerInterceptor 介面的類,比如Spring 已經提供的實現了HandlerInterceptor 介面的抽象類HandlerInterceptorAdapter ;第二種方式是實現Spring的WebRequestInterceptor介面,或者是繼承實現了WebRequestInterceptor的類。

2.2 使用

  1. 請求到達 DispatcherServlet
  2. DispatcherServlet 傳送至 Interceptor ,執行 preHandle
  3. 請求達到 Controller
  4. 請求結束後,postHandle 執行

2.3三個方法

Spring 中主要通過 HandlerInterceptor 介面來實現請求的攔截,實現 HandlerInterceptor 介面需要實現下面三個方法:

preHandle() – 在handler執行之前,返回 boolean 值,true 表示繼續執行,false 為停止執行並返回。
postHandle() – 在handler執行之後, 可以在返回之前對返回的結果進行修改
afterCompletion() – 在請求完全結束後呼叫,可以用來統計請求耗時等等。
(1 )preHandle (HttpServletRequest request, HttpServletResponse response, Object handle) 方法,顧名思義,該方法將在請求處理之前進行呼叫。SpringMVC 中的Interceptor 是鏈式的呼叫的,在一個應用中或者說是在一個請求中可以同時存在多個Interceptor 。每個Interceptor 的呼叫會依據它的宣告順序依次執行,而且最先執行的都是Interceptor 中的preHandle 方法,所以可以在這個方法中進行一些前置初始化操作或者是對當前請求的一個預處理,也可以在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布林值Boolean型別的,當它返回為false 時,表示請求結束,後續的Interceptor 和Controller 都不會再執行;當返回值為true 時就會繼續呼叫下一個Interceptor 的preHandle 方法,如果已經是最後一個Interceptor 的時候就會是呼叫當前請求的Controller 方法。

(2 )postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView) 方法,由preHandle 方法的解釋我們知道這個方法包括後面要說到的afterCompletion 方法都只能是在當前所屬的Interceptor 的preHandle 方法的返回值為true 時才能被呼叫。postHandle 方法,顧名思義就是在當前請求進行處理之後,也就是Controller 方法呼叫之後執行,但是它會在DispatcherServlet 進行檢視返回渲染之前被呼叫,所以我們可以在這個方法中對Controller 處理之後的ModelAndView 物件進行操作。postHandle 方法被呼叫的方向跟preHandle 是相反的,也就是說先宣告的Interceptor 的postHandle 方法反而會後執行,這和Struts2 裡面的Interceptor 的執行過程有點型別。Struts2 裡面的Interceptor 的執行過程也是鏈式的,只是在Struts2 裡面需要手動呼叫ActionInvocation 的invoke 方法來觸發對下一個Interceptor 或者是Action 的呼叫,然後每一個Interceptor 中在invoke 方法呼叫之前的內容都是按照宣告順序執行的,而invoke 方法之後的內容就是反向的。

(3 )afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,該方法也是需要當前對應的Interceptor 的preHandle 方法的返回值為true 時才會執行。顧名思義,該方法將在整個請求結束之後,也就是在DispatcherServlet 渲染了對應的檢視之後執行。這個方法的主要作用是用於進行資源清理工作的。

3. 兩者的比較

  1. filter基於函式回撥,interceptor基於java反射機制;
  2. filter依賴於servlet容器; 攔截器是一個Spring的元件,歸Spring管理,配置在Spring檔案中,因此能使用Spring裡的任何資源、物件,例如 Service物件、資料來源、事務管理等,通過IoC注入到攔截器即可。
  3. filter對所有的請求進行過濾,interceptor只對action請求起作用。
  4. 在action的生命週期裡,Interceptor可以被多次呼叫,而Filter只能在容器初始化時呼叫一次。

一般優先使用interceptor

4 . Filter和interceptor的執行順序

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

5 . Web.xml的執行順序

web.xml 的載入順序是:context-param -> listener -> filter -> servlet