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