Spring Boot攔截器Interceptor與過(guò)濾器Filter深度解析(區(qū)別、實(shí)現(xiàn)與實(shí)戰(zhàn)指南)
Spring Boot攔截器(Interceptor)與過(guò)濾器(Filter)深度解析:區(qū)別、實(shí)現(xiàn)與實(shí)戰(zhàn)指南
一、核心概念對(duì)比
1. 本質(zhì)區(qū)別
維度 | 過(guò)濾器(Filter) | 攔截器(Interceptor) |
---|---|---|
規(guī)范層級(jí) | Servlet規(guī)范(J2EE標(biāo)準(zhǔn)) | Spring MVC框架機(jī)制 |
作用范圍 | 所有請(qǐng)求(包括靜態(tài)資源) | 只處理Controller請(qǐng)求 |
依賴關(guān)系 | 不依賴Spring容器 | 完全集成Spring IOC容器 |
執(zhí)行順序 | 最先執(zhí)行(在DispatcherServlet之前) | 在DispatcherServlet之后執(zhí)行 |
異常處理 | 無(wú)法直接使用Spring的異常處理機(jī)制 | 可以通過(guò)@ControllerAdvice統(tǒng)一處理 |
2. 執(zhí)行流程示意圖
HTTP Request ↓ Filter Chain(doFilter) ↓ DispatcherServlet ↓ Interceptor.preHandle ↓ Controller Method ↓ Interceptor.postHandle ↓ View Rendering(如有) ↓ Interceptor.afterCompletion ↓ Filter Chain(返回響應(yīng))
二、過(guò)濾器(Filter)開(kāi)發(fā)指南
1. 基礎(chǔ)實(shí)現(xiàn)方式
@Component public class LogFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { long startTime = System.currentTimeMillis(); HttpServletRequest req = (HttpServletRequest) request; // 前置處理 System.out.println("Request URI: " + req.getRequestURI()); chain.doFilter(request, response); // 放行請(qǐng)求 // 后置處理 long duration = System.currentTimeMillis() - startTime; System.out.println("Request completed in " + duration + "ms"); } }
2. 高級(jí)配置技巧
@Configuration public class FilterConfig { @Bean public FilterRegistrationBean<LogFilter> loggingFilter() { FilterRegistrationBean<LogFilter> registration = new FilterRegistrationBean<>(); registration.setFilter(new LogFilter()); registration.addUrlPatterns("/api/*"); registration.setOrder(Ordered.HIGHEST_PRECEDENCE); // 設(shè)置優(yōu)先級(jí) return registration; } }
典型應(yīng)用場(chǎng)景:
- 請(qǐng)求日志記錄
- 全局字符編碼設(shè)置
- 跨域處理(CORS)
- XSS防御過(guò)濾
- 請(qǐng)求內(nèi)容壓縮/解壓
三、攔截器(Interceptor)開(kāi)發(fā)指南
1. 標(biāo)準(zhǔn)實(shí)現(xiàn)模板
@Component public class AuthInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("Authorization"); if (!validateToken(token)) { response.sendError(401, "Invalid token"); return false; // 中斷請(qǐng)求 } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // Controller方法執(zhí)行后,視圖渲染前 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 請(qǐng)求完全結(jié)束后(包括視圖渲染) } }
2. 注冊(cè)攔截器配置
@Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private AuthInterceptor authInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns("/**") .excludePathPatterns("/login", "/public/**"); } }
典型應(yīng)用場(chǎng)景:
- 接口權(quán)限驗(yàn)證
- 請(qǐng)求參數(shù)預(yù)處理
- 接口耗時(shí)監(jiān)控
- 敏感操作日志
- 數(shù)據(jù)綁定前校驗(yàn)
四、核心差異深度解析
1. 執(zhí)行順序?qū)Ρ葘?shí)驗(yàn)
配置多個(gè)過(guò)濾器和攔截器時(shí)的執(zhí)行順序:
Filter1 → Filter2 → Interceptor.preHandle → Controller → Interceptor.postHandle → Interceptor.afterCompletion → Filter2 → Filter1
2. 異常處理差異
// 在過(guò)濾器中處理異常 public void doFilter(...) { try { chain.doFilter(request, response); } catch (Exception e) { response.sendError(500, "Server Error"); } } // 在攔截器中處理異常 @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<?> handleException(Exception e) { return ResponseEntity.internalServerError().body("Error occurred"); } }
3. 異步請(qǐng)求處理
// 攔截器需實(shí)現(xiàn)AsyncHandlerInterceptor @Override public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) { // 異步請(qǐng)求的特殊處理 }
五、最佳實(shí)踐與選型策略
1. 技術(shù)選型決策樹
是否需要處理靜態(tài)資源? ├─ 是 → 必須使用Filter └─ 否 → 是否需要訪問(wèn)Spring Bean? ├─ 是 → 選擇Interceptor └─ 否 → 是否需要最早處理請(qǐng)求? ├─ 是 → 選擇Filter └─ 否 → 根據(jù)業(yè)務(wù)復(fù)雜度選擇
2. 性能優(yōu)化建議
- 過(guò)濾器:避免在過(guò)濾器中做復(fù)雜業(yè)務(wù)邏輯
- 攔截器:preHandle方法盡量輕量化
- 兩者都應(yīng)避免:
- 同步阻塞操作
- 頻繁的IO操作
- 大對(duì)象的內(nèi)存操作
3. 常見(jiàn)陷阱規(guī)避
- 過(guò)濾器:
- 忘記調(diào)用chain.doFilter()導(dǎo)致請(qǐng)求阻塞
- 修改請(qǐng)求參數(shù)未使用Wrapper類
- 攔截器:
- 在postHandle中修改ModelAndView導(dǎo)致NPE
- 異步請(qǐng)求中誤用afterCompletion
六、實(shí)戰(zhàn)案例演示
案例1:接口耗時(shí)監(jiān)控系統(tǒng)
// 攔截器實(shí)現(xiàn) public class MetricsInterceptor implements HandlerInterceptor { private static final ThreadLocal<Long> startTime = new ThreadLocal<>(); @Override public boolean preHandle(...) { startTime.set(System.currentTimeMillis()); return true; } @Override public void afterCompletion(...) { long duration = System.currentTimeMillis() - startTime.get(); metricsService.recordRequestTime(request.getRequestURI(), duration); startTime.remove(); } }
案例2:全局防重放攻擊過(guò)濾器
public class ReplayAttackFilter implements Filter { private Cache<String, Boolean> requestCache = Caffeine.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build(); @Override public void doFilter(...) { String nonce = request.getHeader("X-Nonce"); if (requestCache.getIfPresent(nonce) != null) { response.sendError(400, "Duplicate request"); return; } requestCache.put(nonce, true); chain.doFilter(request, response); } }
七、擴(kuò)展知識(shí)
1. 與AOP的區(qū)別
- AOP:
- 基于代理模式實(shí)現(xiàn)
- 可以精確控制到具體方法
- 更適合業(yè)務(wù)層面的切面處理
- 攔截器:
- 基于HandlerMapping實(shí)現(xiàn)
- 主要針對(duì)HTTP請(qǐng)求生命周期
- 更適合Web層通用處理
2. 高級(jí)應(yīng)用場(chǎng)景
- 過(guò)濾器鏈:實(shí)現(xiàn)責(zé)任鏈模式
- 攔截器棧:組合多個(gè)攔截邏輯
- 動(dòng)態(tài)啟用/禁用:結(jié)合配置中心實(shí)現(xiàn)
總結(jié)建議
- 優(yōu)先使用攔截器處理Web層通用邏輯
- 保留過(guò)濾器用于底層請(qǐng)求處理
- 復(fù)雜場(chǎng)景可以組合使用兩者
- 生產(chǎn)環(huán)境務(wù)必進(jìn)行性能壓測(cè)
通過(guò)合理運(yùn)用過(guò)濾器和攔截器,開(kāi)發(fā)者可以構(gòu)建出高可維護(hù)性的Web應(yīng)用架構(gòu)。建議結(jié)合APM工具(如SkyWalking)監(jiān)控兩者的執(zhí)行效率,持續(xù)優(yōu)化系統(tǒng)性能。
到此這篇關(guān)于Spring Boot攔截器(Interceptor)與過(guò)濾器(Filter)深度解析:區(qū)別、實(shí)現(xiàn)與實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Spring Boot攔截器與過(guò)濾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot?過(guò)濾器、攔截器、全局異常處理的方案處理小結(jié)
- SpringBoot項(xiàng)目如何設(shè)置權(quán)限攔截器和過(guò)濾器
- Springboot項(xiàng)目Aop與攔截器與過(guò)濾器橫向?qū)Ρ?/a>
- SpringBoot實(shí)現(xiàn)過(guò)濾器和攔截器的方法
- SpringBoot面試突擊之過(guò)濾器和攔截器區(qū)別詳解
- SpringBoot實(shí)現(xiàn)過(guò)濾器攔截器的耗時(shí)對(duì)比
- SpringBoot 過(guò)濾器與攔截器實(shí)例演示
- springboot過(guò)濾器和攔截器的實(shí)例代碼
相關(guān)文章
SpringBoot返回前端Long類型字段丟失精度問(wèn)題及解決方案
Java服務(wù)端返回Long整型數(shù)據(jù)給前端,JS會(huì)自動(dòng)轉(zhuǎn)換為Number類型,本文主要介紹了SpringBoot返回前端Long類型字段丟失精度問(wèn)題及解決方案,感興趣的可以了解一下2024-03-03SpringBoot接收f(shuō)orm-data和x-www-form-urlencoded數(shù)據(jù)的方法
form-data和x-www-form-urlencoded是兩種不同的HTTP請(qǐng)求體格式,本文主要介紹了SpringBoot接收f(shuō)orm-data和x-www-form-urlencoded數(shù)據(jù)的方法,具有一定的參考價(jià)值,感興趣的可以了解一下2024-05-05Spring 自動(dòng)裝配的二義性實(shí)例解析
這篇文章主要介紹了Spring 自動(dòng)裝配的二義性實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Spring Boot中Bean定義方調(diào)用方式解析
這篇文章主要介紹了Spring Boot中Bean定義方調(diào)用方式解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法
這篇文章主要介紹了SpringMVC中使用@PathVariable綁定路由中的數(shù)組的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Servlet3.0實(shí)現(xiàn)文件上傳的方法
本篇文章主要介紹了Servlet實(shí)現(xiàn)文件上傳的方法,所謂文件上傳就是將本地的文件發(fā)送到服務(wù)器中保存。有興趣的可以了解一下。2017-03-03