目錄
- 一、攔截器(Interceptor)和過濾器(Filter):都是“守門員”!
- 二、如何實現攔截器和過濾器?
- 三、攔截器和過濾器的區別
- 四、執行順序
- 五、真實的應用場景
- 六、總結
🌟如果喜歡作者的講解方式,關注作者不迷路,同時也可以看看我的其他文章! 感謝!!!
🌟 從樂高積木到樂隊指揮,用最通俗易懂的方式帶你玩轉 Spring Boot Bean!
就讓我用這篇文章來講解 SpringBoot 的攔截器和過濾器吧,給它安排明白!😎
一、攔截器(Interceptor)和過濾器(Filter):都是“守門員”!
想象一下,你的 SpringBoot 應用就像一個豪華酒店🏨。
- 過濾器(Filter): 就像酒店大門口的保安👮,負責檢查所有進出酒店的人(請求)。它可以決定是否允許客人進入,或者在客人進入前做一些處理,比如檢查身份證、測量體溫🌡?。
- 攔截器(Interceptor): 就像酒店內部各個樓層的樓層經理👩?💼,只負責檢查進入特定樓層(Controller)的客人。它可以在客人進入樓層前、進入樓層后、離開樓層后都進行干預,比如登記訪客信息、提供樓層指引🗺?。
二、如何實現攔截器和過濾器?
1. 過濾器(Filter):
- 步驟一: 創建一個類,實現
javax.servlet.Filter
接口。 - 步驟二: 實現
doFilter()
方法。這個方法就是過濾器的核心邏輯,在這里你可以對請求和響應進行處理。 - 步驟三: 使用
@WebFilter
注解或者在WebConfig
類中注冊過濾器。
// 方式一:使用 @WebFilter 注解
@WebFilter(urlPatterns = "/*", filterName = "MyFilter") // 攔截所有請求
public class MyFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("過濾器:請求來了!我要檢查一下!🧐");// 可以對 request 和 response 進行處理HttpServletRequest req = (HttpServletRequest) request;String uri = req.getRequestURI();System.out.println("請求的URI:" + uri);// 放行,讓請求繼續往下走chain.doFilter(request, response);System.out.println("過濾器:請求走了!我要記錄一下!📝");}
}// 方式二:在 WebConfig 類中注冊
@Configuration
public class WebConfig {@Beanpublic FilterRegistrationBean<MyFilter> myFilterRegistrationBean() {FilterRegistrationBean<MyFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new MyFilter());registration.addUrlPatterns("/*"); // 攔截所有請求registration.setName("MyFilter");registration.setOrder(1); // 設置優先級,數字越小優先級越高return registration;}
}
2. 攔截器(Interceptor):
- 步驟一: 創建一個類,實現
org.springframework.web.servlet.HandlerInterceptor
接口。 - 步驟二: 實現
preHandle()
、postHandle()
、afterCompletion()
方法。preHandle()
:在 Controller 處理請求之前調用,可以進行權限驗證、參數校驗等。如果返回false
,則請求會被攔截,不會繼續執行。postHandle()
:在 Controller 處理請求之后,但在視圖渲染之前調用,可以對 ModelAndView 進行修改。afterCompletion()
:在整個請求處理完畢之后調用,可以進行資源清理、日志記錄等。
- 步驟三: 創建一個配置類,實現
org.springframework.web.servlet.config.annotation.WebMvcConfigurer
接口,并重寫addInterceptors()
方法,將攔截器注冊到 Spring 容器中。
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("攔截器:Controller 要處理請求了!我要先檢查一下!👮?♀?");// 可以進行權限驗證、參數校驗等String token = request.getHeader("token");if (token == null || token.isEmpty()) {System.out.println("攔截器:沒有 token,拒絕訪問!🚫");response.setStatus(401); // 返回未授權狀態碼return false; // 攔截請求}return true; // 放行請求}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("攔截器:Controller 處理完請求了!我可以修改 ModelAndView!🎨");// 可以對 ModelAndView 進行修改if (modelAndView != null) {modelAndView.addObject("message", "攔截器添加的額外信息!🎁");}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("攔截器:請求處理完成了!我可以清理資源、記錄日志!🧹");// 可以進行資源清理、日志記錄等}
}@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/api/**") // 攔截 /api/ 下的所有請求.excludePathPatterns("/api/login"); // 排除 /api/login 請求}
}
三、攔截器和過濾器的區別
特性 | 過濾器(Filter) | 攔截器(Interceptor) |
---|---|---|
實現方式 | 實現 javax.servlet.Filter 接口 | 實現 org.springframework.web.servlet.HandlerInterceptor 接口 |
攔截范圍 | 攔截所有進出 Servlet 容器的請求 | 攔截特定的 Controller 方法 |
執行時機 | 在 DispatcherServlet 之前和之后執行 | 在 Controller 方法執行之前、之后和完成之后執行 |
依賴性 | 不依賴 Spring 容器 | 依賴 Spring 容器,可以訪問 Spring 上下文 |
功能 | 字符編碼轉換、請求內容過濾、敏感詞過濾等 | 權限驗證、日志記錄、參數校驗等 |
精確度 | 粗粒度,只能攔截 URL | 細粒度,可以訪問 HandlerMethod,獲取方法信息 |
總結:
- 過濾器: 攔截所有請求,不依賴 Spring,功能比較通用。
- 攔截器: 攔截特定 Controller 方法,依賴 Spring,功能更精細。
四、執行順序
- 過濾器(Filter):在 DispatcherServlet 之前執行。
- 攔截器(Interceptor):
preHandle()
:在 Controller 方法執行之前執行。- Controller 方法執行。
postHandle()
:在 Controller 方法執行之后,但在視圖渲染之前執行。- 視圖渲染。
afterCompletion()
:在整個請求處理完畢之后執行。
記住: 多個過濾器和攔截器可以配置執行順序,通常通過 order
屬性或者 @Order
注解來設置,數字越小優先級越高。
五、真實的應用場景
- 過濾器:
- 字符編碼轉換: 統一設置請求和響應的字符編碼,避免亂碼。
- XSS 攻擊防御: 過濾請求中的惡意腳本,防止 XSS 攻擊。
- 日志記錄: 記錄所有請求的 URL、IP 地址等信息。
- 攔截器:
- 權限驗證: 檢查用戶是否已登錄,是否有權限訪問特定資源。
- 參數校驗: 校驗請求參數的合法性,防止惡意請求。
- 性能監控: 記錄 Controller 方法的執行時間,分析性能瓶頸。
- 防止重復提交: 避免用戶重復提交表單。
六、總結
- 過濾器: 就像酒店大門口的保安,啥人都攔,主要做一些通用的檢查,比如身份證、體溫啥的。
- 攔截器: 就像樓層經理,只管特定樓層的人,可以做更細致的檢查,比如登記訪客信息、提供樓層指引。
- 執行順序: 先保安,再樓層經理。保安先檢查,樓層經理在客人進房間前、進房間后、離開房間后都可以管。
如果編寫了AOP邏輯,會在攔截器之后執行,相關內容請看:
🔗被重復代碼逼瘋?AOP來當“舔狗”!日志/事務/權限,隨叫隨到!
希望這篇文章能讓你有趣的理解 SpringBoot 的攔截器和過濾器!🎉🎉🎉