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

1、過濾器:

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

2、攔截器:

依賴於web框架,在SpringMVC中就是依賴於SpringMVC框架。在實現上基於Java的反射機制,屬於面向切面編程(AOP)的一種運用。由於攔截器是基於web框架的調用,因此可以使用Spring的依賴注入(DI)進行一些業務操作,同時一個攔截器實例在一個controller生命週期之內可以多次調用。但是缺點是隻能對controller請求進行攔截,對其他的一些比如直接訪問靜態資源的請求則沒辦法進行攔截處理

3、過濾器和攔截器的區別

①攔截器是基於java的反射機制的,而過濾器是基於函數回調。
②攔截器不依賴與servlet容器,過濾器依賴與servlet容器。
③攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用。
④攔截器可以訪問action上下文、值棧裏的對象,而過濾器不能訪問。
⑤在action的生命週期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次。
⑥攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,這點很重要,在攔截器裏注入一個service,可以調用業務邏輯。

  • 過濾器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
        System.out.println("before...");
        chain.doFilter(request, response);//放行
        System.out.println("after...");
    }

chain.doFilter(request, response);這個方法的調用作爲分水嶺。事實上調用Servlet的doService()方法是在chain.doFilter(request, response);這個方法中進行的。

  • 攔截器
    攔截器是被包裹在過濾器之中的。
 @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {
      System.out.println("preHandle");
      return true;
  }
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception {
      System.out.println("postHandle");
  }
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {
      System.out.println("afterCompletion");
  }

a.preHandle()這個方法是在過濾器的chain.doFilter(request, response)方法的前一步執行,也就是在 System.out.println("before...")chain.doFilter(request, response)之間執行。

b.preHandle()方法之後,在return ModelAndView之前進行,可以操控Controller的ModelAndView內容。

c.afterCompletion()方法是在過濾器返回給前端前一步執行,也就是在chain.doFilter(request, response)System.out.println("after...")之間執行。

SpringMVC的機制是由同一個Servlet來分發請求給不同的Controller,其實這一步是在Servlet的service()方法中執行的。所以過濾器、攔截器、service()方法,dispatcher()方法的執行順序應該是這樣的,大致畫了個圖:其實非常好測試,自己寫一個過濾器,一個攔截器,然後在這些方法中都加個斷點,一路F8下去就得出了結論。
在這裏插入圖片描述

4、圖解

  • 攔截器和過濾器區別:
    在這裏插入圖片描述

  • 過濾器和攔截器觸發時機不一樣,過濾器是在請求進入容器後,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完後,返回給前端之前。
    如下圖:(圖中攔截器單詞應爲Interceptor)
    在這裏插入圖片描述

  • 攔截器可以獲取IOC容器中的各個bean,而過濾器就不行,因爲攔截器是spring提供並管理的,spring的功能可以被攔截器使用,在攔截器裏注入一個service,可以調用業務邏輯。而過濾器是JavaEE標準,只需依賴servlet api ,不需要依賴spring。
    過濾器攔截器運行先後步驟:
    在這裏插入圖片描述
    其中第2步,SpringMVC的機制是由DispatcherServlet來分發請求給不同的Controller,其實這一步是在Servlet的service()方法中執行的.

  • 前面我們知道過濾器的實現基於回調函數。而攔截器(代理模式)的實現基於反射,代理分靜態代理和動態代理,動態代理是攔截器的簡單實現。何時使用攔截器?何時使用過濾器?
    (1)如果是非spring項目,那麼攔截器不能用,只能使用過濾器。
    (2)如果是處理controller前後,既可以使用攔截器也可以使用過濾器。
    (3)如果是處理dispaterServlet前後,只能使用過濾器。
    在這裏插入圖片描述

參考鏈接:
1、https://www.jianshu.com/p/7bd0cad17f23
2、https://www.cnblogs.com/lgjava/p/10559356.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章