過濾器、監聽器、攔截器的區別
- 過濾器(filter)、監聽器(Listener)是JavaWeb的三大組件。
- 而攔截器(Interceptor)是Spring框架中的。
我們主要是要分清除過濾器和攔截器的區別:
- 實現原理:過濾器是基于函數回調實現的,而攔截器是基于java的反射機制。
- 使用范圍:過濾器Filter的使用要依賴于Tomcat等容器,導致它只能在web程序中使用。而攔截器是可以單獨使用的。不僅能應用在web程序中,也可以用于Application、Swing等程序中。
- 觸發時機:
從圖中我看可以看出,過濾器Filter是在請求進入容器后,但請求進入servlet之前進行預處理的。請求結束返回也是,是在servlet處理完后,返回給前端之前。而攔截器Interceptor是在請求進入servlet后,在進入Controller之前進行預處理的,Controller中渲染了對應的視圖之后請求結束。
執行順序
配置Filter:
package com.qcby.demo.config;import org.springframework.stereotype.Component;import javax.servlet.*;
import java.io.IOException;@Component
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {System.out.println("Filter 前置過濾");}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("Filter 處理中");filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {System.out.println("Filter 后置過濾");}
}
自定義攔截器:
package com.qcby.demo.config;import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Interceptor 前置攔截");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor 后置攔截");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Interceptor 最終攔截");}
}
配置攔截器:
package com.qcby.demo.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class MyConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**") // 設置要攔截的.excludePathPatterns("/test1");// 設置不攔截的}
}
控制器:
package com.qcby.demo;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("test")
public class TestController {@GetMapping("/test1")public String test() {return "123456";}
}
項目啟動之后,我們會發現過濾器的init()方法,隨著容器的啟動進行了初始化:
然后瀏覽器訪問對應的端口號:http://localhost:8080/test/test1,會有以下輸出:
這樣就驗證了我們前邊的過濾器和攔截器的觸發順序。
對于攔截器的觸發時機,在只有一個攔截器時:
有多個攔截器時:
過濾器的應用場景
- 過濾敏感詞匯(防止sql注入)
- 設置字符編碼
- URL級別的權限訪問控制
- 壓縮響應信息
攔截器的應用場景
- 登錄驗證,判斷用戶是否登錄。
- 權限驗證,判斷用戶是否有權限訪問資源,如校驗token
- 日志記錄,記錄請求操作日志(用戶ip,訪問時間等),以便統計請求訪問量。
- 處理cookie、本地化、國際化、主題等。
- 性能監控,監控請求處理時長等。
- 通用行為:讀取cookie得到用戶信息并將用戶對象放入請求,從而方便后續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實現)
參考文獻
- Springboot——攔截器
- 過濾器 和 攔截器的 6個區別,別再傻傻分不清了