filter和interceptor的區別

經典雞翅發表於2020-04-29

前言

最近在面試的時候,被問到了這個問題,覺得答得不是很好,在此進行整理和記錄,供自己學習,也希望能幫助到大家。

什麼是Filter

在java的javax.servlet下有一個介面Filter。任何實現了Filter介面的類都可以稱之為filter。Filter的主要用途是設定字符集、控制許可權、控制轉向等等。在使用filter的過程中,如果是傳統的web專案,帶有web.xml檔案這種。我們需要在xml裡面進行配置。比如下面這樣。

    <filter>
        <description>字符集過濾器</description>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <description>字符集編碼</description>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

這種使用方式直接將我們的請求和響應的字符集全部改為utf-8的形式。

如果是在spingboot這種專案中使用,我們定義好自己的filter類之後,需要使用filterregisterbean將filter進行注入。

Filter隨著專案的啟動而啟動,只初始化一次,隨著web專案的停止而銷燬。

Filter主要用於對使用者請求的預處理和程式返回response的後處理。可以在請求到達servlet之前進行request的處理或者新增頭和一些其他資料。或者在reponse到達之前,修改response的頭和資料。

filter中總共有三個方法。
void init(FilterConfig config):用於完成Filter的初始化。
void destory():用於filter銷燬前,完成資源的回收。
void doFilter(ServletRequest request,ServletResponse response,FilterChain chain):該方法是filter的核心過濾方法。通過request進行請求處理,然後呼叫chain.doFilter。呼叫完之後,可以通過response進行響應處理。

攔截器

攔截器是aop的一種實現方案,是aop思想的體現。在我們呼叫方法之前,呼叫攔截器的一個方法或者在呼叫方法之後,呼叫攔截器的一個方法。

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

(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方法反而會後執行。

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

需要注意的點就是當preHandler為true的時候,postHandler才能執行。當為false的時候,afterCompletion仍然會執行。

filter和interceptor的區別總結

1、filter介面在javax.servlet包下面。inteceptor定義在org.springframework.web.servlet中。
2、filter是servlet規定的,interceptor即可用於web程式,也可用於application中。
3、filter是servlet容器支援的,interceptor是spring框架支援的。
4、filter通過dochain放行,interceptor通過prehandler放行。
5、filter只在方法前後執行,interceptor粒度更細,可以深入到方法前後,異常丟擲前後。

相關文章