Spring Boot攔截器Interceptor與過(guò)濾器Filter詳細(xì)教程(示例詳解)
Spring Boot攔截器(Interceptor)與過(guò)濾器(Filter)詳細(xì)教程
1. 概述
1.1 什么是攔截器(Interceptor)?
攔截器是 Spring MVC 框架的組件,基于 AOP(面向切面編程) 實(shí)現(xiàn)。它允許在請(qǐng)求處理的不同階段(如Controller方法執(zhí)行前后)插入自定義邏輯。
1.2 什么是過(guò)濾器(Filter)?
過(guò)濾器是 Java Servlet規(guī)范 定義的組件,作用于所有進(jìn)入容器的請(qǐng)求(如Tomcat)。它可以在請(qǐng)求到達(dá)Servlet前或響應(yīng)返回客戶端前進(jìn)行預(yù)處理和后處理。
1.3 核心區(qū)別
特性 | 攔截器(Interceptor) | 過(guò)濾器(Filter) |
---|---|---|
所屬框架 | Spring MVC | Servlet API |
作用范圍 | 僅Spring MVC管理的請(qǐng)求 | 所有請(qǐng)求(包括靜態(tài)資源) |
依賴 | 依賴Spring容器 | 依賴Servlet容器(如Tomcat) |
執(zhí)行時(shí)機(jī) | Controller方法前后 | Servlet處理前后 |
獲取Bean | 支持(通過(guò)Spring上下文) | 不支持(需通過(guò)其他方式注入) |
2. 使用場(chǎng)景
2.1 攔截器的典型應(yīng)用
- 日志記錄:記錄請(qǐng)求參數(shù)、響應(yīng)時(shí)間。
- 權(quán)限驗(yàn)證:檢查用戶是否登錄或擁有權(quán)限。
- 事務(wù)管理:在Controller方法前后開(kāi)啟/提交事務(wù)。
- 性能監(jiān)控:統(tǒng)計(jì)接口耗時(shí)。
2.2 過(guò)濾器的典型應(yīng)用
- 全局字符編碼:統(tǒng)一設(shè)置請(qǐng)求/響應(yīng)的編碼(如UTF-8)。
- 跨域處理:添加CORS響應(yīng)頭。
- XSS防御:過(guò)濾請(qǐng)求參數(shù)中的惡意腳本。
- 請(qǐng)求壓縮:對(duì)響應(yīng)內(nèi)容進(jìn)行GZIP壓縮。
3. 實(shí)現(xiàn)步驟
3.1 創(chuàng)建攔截器
步驟:
實(shí)現(xiàn) HandlerInterceptor
接口,重寫(xiě)以下方法:
preHandle()
:在Controller方法執(zhí)行前調(diào)用。postHandle()
:在Controller方法執(zhí)行后、視圖渲染前調(diào)用。afterCompletion()
:在請(qǐng)求完成后調(diào)用(視圖渲染后)。
注冊(cè)攔截器到Spring MVC配置。
代碼示例:
public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 檢查用戶是否登錄 if (request.getSession().getAttribute("user") == null) { response.sendRedirect("/login"); return false; // 中斷請(qǐng)求 } return true; } }
注冊(cè)攔截器:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new AuthInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login", "/static/**"); } }
注冊(cè)多個(gè)攔截器:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 第一個(gè)攔截器:日志(優(yōu)先級(jí)高) registry.addInterceptor(new LogInterceptor()) .addPathPatterns("/**") // 攔截所有路徑 .excludePathPatterns("/static/**"); // 排除靜態(tài)資源 // 第二個(gè)攔截器:權(quán)限(優(yōu)先級(jí)低) registry.addInterceptor(new AuthInterceptor()) .addPathPatterns("/api/**"); // 僅攔截/api路徑 } }
關(guān)鍵配置選項(xiàng)
配置方法 | 說(shuō)明 |
---|---|
addPathPatterns("/api") | 指定攔截的路徑(支持Ant風(fēng)格) |
excludePathPatterns("/login") | 排除特定路徑 |
order(1) | 顯式設(shè)置順序(默認(rèn)按注冊(cè)順序) |
若要手動(dòng)指定順序,可添加:
registry.addInterceptor(new LogInterceptor()).order(1); registry.addInterceptor(new AuthInterceptor()).order(2);
3.2 創(chuàng)建過(guò)濾器
步驟:
- 實(shí)現(xiàn)
javax.servlet.Filter
接口,重寫(xiě)doFilter
方法。 - 注冊(cè)過(guò)濾器到Servlet容器(通過(guò)注解或配置類)。
代碼示例:
@WebFilter(urlPatterns = "/*") public class LoggingFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("請(qǐng)求開(kāi)始: " + ((HttpServletRequest) request).getRequestURI()); chain.doFilter(request, response); // 繼續(xù)執(zhí)行后續(xù)過(guò)濾器或Servlet System.out.println("請(qǐng)求結(jié)束"); } }
注冊(cè)過(guò)濾器(若未使用@WebFilter):
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean<LoggingFilter> loggingFilter() { FilterRegistrationBean<LoggingFilter> bean = new FilterRegistrationBean<>(); bean.setFilter(new LoggingFilter()); bean.addUrlPatterns("/*"); bean.setOrder(1); // 設(shè)置執(zhí)行順序 return bean; } }
注意: 確保主類添加 @ServletComponentScan
以啟用 @WebFilter
注解。
4. 執(zhí)行順序與流程
4.1 執(zhí)行順序
- 過(guò)濾器(FilterChain) → 2. 攔截器(preHandle) → 3. Controller方法 → 4. 攔截器(postHandle) → 5. 視圖渲染 → 6. 攔截器(afterCompletion) → 7. 過(guò)濾器后續(xù)處理
4.2 流程圖
客戶端 → Filter.doFilter() → Interceptor.preHandle() → Controller → Interceptor.postHandle() → 視圖渲染 → Interceptor.afterCompletion() → Filter.doFilter()后續(xù)處理 → 客戶端
5. 常見(jiàn)問(wèn)題與解決方案
Q1:如何控制多個(gè)攔截器/過(guò)濾器的執(zhí)行順序?
- 攔截器:通過(guò)
registry.addInterceptor()
的順序決定。 - 過(guò)濾器:通過(guò)
FilterRegistrationBean.setOrder()
設(shè)置優(yōu)先級(jí)(值越小越先執(zhí)行)。
Q2:攔截器中如何獲取Spring管理的Bean?
直接從Spring容器注入:
public class AuthInterceptor implements HandlerInterceptor { @Autowired private UserService userService; // 直接注入 }
Q3:過(guò)濾器中如何修改請(qǐng)求參數(shù)?
通過(guò)自定義 HttpServletRequestWrapper
:
public class ModifyRequestWrapper extends HttpServletRequestWrapper { // 重寫(xiě)getParameter等方法以修改參數(shù) } // 在Filter中替換Request對(duì)象 chain.doFilter(new ModifyRequestWrapper(request), response);
Q4:攔截器和過(guò)濾器執(zhí)行時(shí)出現(xiàn)異常如何處理?
- 攔截器:在
afterCompletion
中處理異常。 - 過(guò)濾器:使用
try-catch
包裹chain.doFilter()
。
Q5:如何讓某個(gè)攔截器全局生效?
使用 addPathPatterns("/**")
:
registry.addInterceptor(new LogInterceptor()) .addPathPatterns("/**");
Q6:如何跳過(guò)特定攔截器的執(zhí)行?
在 preHandle
中返回 false
:
@Override public boolean preHandle(...) { if (跳過(guò)條件) { return false; // 后續(xù)攔截器和Controller不會(huì)執(zhí)行 } return true; }
Q7:攔截器之間如何共享數(shù)據(jù)?
通過(guò) request.setAttribute
傳遞:
// 在第一個(gè)攔截器中存儲(chǔ)數(shù)據(jù) request.setAttribute("key", "value"); // 在后續(xù)攔截器中獲取 String value = (String) request.getAttribute("key");
6. 總結(jié)
選擇攔截器還是過(guò)濾器?
- 需要訪問(wèn)Spring上下文或Controller信息 → 攔截器。
- 需處理所有請(qǐng)求(包括靜態(tài)資源) → 過(guò)濾器。
最佳實(shí)踐:
- 優(yōu)先使用攔截器處理業(yè)務(wù)相關(guān)邏輯。
- 使用過(guò)濾器處理底層Servlet容器的任務(wù)(如編碼、壓縮)。
到此這篇關(guān)于Spring Boot攔截器(Interceptor)與過(guò)濾器(Filter)詳細(xì)教程的文章就介紹到這了,更多相關(guān)Spring Boot攔截器與過(guò)濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot?過(guò)濾器、攔截器、全局異常處理的方案處理小結(jié)
- Springboot中使用攔截器、過(guò)濾器、監(jiān)聽(tīng)器的流程分析
- Spring?Boot中的過(guò)濾器攔截器監(jiān)聽(tīng)器使用技巧匯總
- springboot配置過(guò)濾器和多個(gè)攔截器、執(zhí)行順序(案例詳解)
- SpringBoot項(xiàng)目如何設(shè)置權(quán)限攔截器和過(guò)濾器
- SpringBoot使用過(guò)濾器、攔截器和監(jiān)聽(tīng)器的案例代碼(Springboot搭建java項(xiàng)目)
- SpringBoot 過(guò)濾器、攔截器、監(jiān)聽(tīng)器對(duì)比及使用場(chǎng)景分析
- Springboot項(xiàng)目Aop與攔截器與過(guò)濾器橫向?qū)Ρ?/a>
- SpringBoot實(shí)現(xiàn)過(guò)濾器、攔截器與切片的實(shí)現(xiàn)和區(qū)別
- 詳談springboot過(guò)濾器和攔截器的實(shí)現(xiàn)及區(qū)別
- Spring Boot使用過(guò)濾器和攔截器分別實(shí)現(xiàn)REST接口簡(jiǎn)易安全認(rèn)證示例代碼詳解
相關(guān)文章
如何實(shí)現(xiàn)java執(zhí)行kettle并傳參數(shù)
文章主要介紹了在審批成功后如何使用Kettle傳遞批次號(hào)參數(shù)并執(zhí)行KTR文件,同時(shí),提到了所需的主要POM依賴,并強(qiáng)調(diào)了個(gè)人經(jīng)驗(yàn)的價(jià)值,鼓勵(lì)大家參考和使用2025-01-01restTemplate未設(shè)置連接數(shù)導(dǎo)致服務(wù)雪崩問(wèn)題以及解決
面對(duì)線上問(wèn)題,仔細(xì)分析原因,及時(shí)調(diào)整配置,能有效解決問(wèn)題,本文詳細(xì)描述了線上遇到流量突增引發(fā)的問(wèn)題,通過(guò)查看代碼和連接池信息,分析出問(wèn)題的原因是連接池滿了,連接池大小配置不足以應(yīng)對(duì)大并發(fā)流量,通過(guò)調(diào)整連接池大小配置2024-10-10java+jdbc+mysql+socket搭建局域網(wǎng)聊天室
這篇文章主要為大家詳細(xì)介紹了java+jdbc+mysql+socket搭建局域網(wǎng)聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01IDEA加載項(xiàng)目沒(méi)有src目錄的問(wèn)題及解決
這篇文章主要介紹了IDEA加載項(xiàng)目沒(méi)有src目錄的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12Java求s=a+aa+aaa+aaaa+aa...a 5個(gè)數(shù)相加的值
求s=a+aa+aaa+aaaa+aa...a的值,其中a是一個(gè)數(shù)字。例如2+22+222+2222+22222(此時(shí)共有5個(gè)數(shù)相加),幾個(gè)數(shù)相加有鍵盤(pán)控制2017-02-02springboot CompletableFuture異步線程池詳解
這篇文章主要介紹了springboot CompletableFuture異步線程池的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04