filter和interceptor的區別

前言

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

什麼是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粒度更細,可以深入到方法前後,異常拋出前後。

Tags: