SpringMvc(Interceptor,Filter)實(shí)現(xiàn)方案
在 Java Web 開發(fā)中,過(guò)濾器 (Filter) 和 攔截器 (Interceptor) 都是常用的 AOP(面向切面編程)實(shí)現(xiàn)方式,但它們所屬的框架層級(jí)和執(zhí)行時(shí)機(jī)有很大不同。
我們可以把它們想象成進(jìn)入大樓的保安(過(guò)濾器)和進(jìn)入辦公室前的秘書(攔截器)。
1. 過(guò)濾器 (Filter)
過(guò)濾器屬于 Servlet 規(guī)范,它位于所有 Servlet 之前。它可以對(duì)幾乎所有的請(qǐng)求(HTML、圖片、JS、路徑等)進(jìn)行預(yù)處理。
實(shí)現(xiàn)方案一:通過(guò)@WebFilter注解(Servlet 原生)
這是最簡(jiǎn)單、最直接的方式,不需要額外的配置類。
- 實(shí)現(xiàn)步驟:
- 實(shí)現(xiàn)
jakarta.servlet.Filter接口。 - 重寫
doFilter方法。 - 在類上標(biāo)注
@WebFilter(urlPatterns = "/*")。 - 在啟動(dòng)類上加
@ServletComponentScan。
- 實(shí)現(xiàn)
實(shí)現(xiàn)方案二:通過(guò)FilterRegistrationBean(Spring Boot統(tǒng)一管理生命周期 推薦)
如果你需要更精細(xì)地控制過(guò)濾器的執(zhí)行順序(Order),或者你的過(guò)濾器是第三方庫(kù)提供的,這種方案最合適。
- 實(shí)現(xiàn)步驟:
- 編寫一個(gè)普通的類實(shí)現(xiàn)
Filter接口。 - 創(chuàng)建一個(gè)配置類(標(biāo)注
@Configuration)。 - 定義一個(gè)
Bean返回FilterRegistrationBean實(shí)例。
- 編寫一個(gè)普通的類實(shí)現(xiàn)
@Bean
public FilterRegistrationBean<MyFilter> registrationBean() {
FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new MyFilter()); // 設(shè)置過(guò)濾器
bean.addUrlPatterns("/api/*"); // 設(shè)置攔截路徑
bean.setOrder(1); // 設(shè)置優(yōu)先級(jí),數(shù)字越小越靠前
return bean;
}2. 攔截器 (Interceptor)
攔截器屬于 Spring MVC 框架。它只能攔截發(fā)送到 Controller 的請(qǐng)求。因?yàn)樗?Spring 容器中,所以它可以直接使用 Spring 注入的對(duì)象(比如 Service)。
需要繼承/實(shí)現(xiàn)的類
- 實(shí)現(xiàn)接口:
org.springframework.web.servlet.HandlerInterceptor。 - 主要方法:
preHandle:在 Controller 執(zhí)行前調(diào)用(常用作權(quán)限校驗(yàn))。postHandle:Controller 執(zhí)行后,視圖渲染前調(diào)用。afterCompletion:整個(gè)請(qǐng)求結(jié)束(視圖渲染后)調(diào)用,常用于清理資源。
注冊(cè)攔截器
實(shí)現(xiàn)攔截器后,必須將其注冊(cè)到 Spring MVC 的配置中:
- 繼承
WebMvcConfigurer接口。 - 重寫
addInterceptors方法。
3. 核心區(qū)別對(duì)比表
| 特性 | 過(guò)濾器 (Filter) | 攔截器 (Interceptor) |
| 所屬框架 | Servlet 容器 (如 Tomcat) | Spring MVC 框架 |
| 實(shí)現(xiàn)接口 | jakarta.servlet.Filter | HandlerInterceptor |
| 攔截范圍 | 幾乎所有請(qǐng)求 (URL 匹配即可) | 僅針對(duì) Controller 的請(qǐng)求 |
| 注入能力 | 較難直接注入 Spring Bean | 完美支持注入 Bean |
| 執(zhí)行時(shí)機(jī) | 在 Servlet 之前執(zhí)行 | 在 Servlet 之后,Controller 之前執(zhí)行 |
| 主要用途 | 編碼設(shè)置、敏感詞過(guò)濾、全局壓縮 | 權(quán)限檢查、日志記錄、參數(shù)預(yù)處理 |
簡(jiǎn)單總結(jié):
- 過(guò)濾器:適合做底層的、通用的操作(如:字符編碼、請(qǐng)求跨域、全局加密)。
- 攔截器:適合做業(yè)務(wù)相關(guān)的操作(如:檢查是否登錄、接口權(quán)限控制、記錄操作日志)。
為什么跨域請(qǐng)求要通過(guò)過(guò)濾器實(shí)現(xiàn)?
其實(shí)跨域(CORS)既可以通過(guò)**過(guò)濾器(Filter)實(shí)現(xiàn),也可以通過(guò)攔截器(Interceptor)**或者 Spring 提供的 @CrossOrigin 注解實(shí)現(xiàn)。
但在實(shí)際生產(chǎn)中,絕大多數(shù)架構(gòu)師會(huì)首選過(guò)濾器。這主要源于跨域請(qǐng)求的一個(gè)特殊機(jī)制:預(yù)檢請(qǐng)求(Preflight Request)。
1. 預(yù)檢請(qǐng)求(OPTIONS)的攔路虎
當(dāng)瀏覽器發(fā)現(xiàn)你在發(fā)起一個(gè)“復(fù)雜請(qǐng)求”(比如帶了自定義 Header 或 Content-Type 為 application/json)時(shí),它會(huì)先自動(dòng)發(fā)送一個(gè) OPTIONS 方法的探測(cè)請(qǐng)求。
- 過(guò)濾器的優(yōu)勢(shì):由于過(guò)濾器在 Servlet 容器的最外層,它能在請(qǐng)求到達(dá) Spring MVC 的
DispatcherServlet之前,就識(shí)別出這是一個(gè) OPTIONS 請(qǐng)求,并直接返回允許跨域的響應(yīng)頭(200 OK)。 - 攔截器的劣勢(shì):攔截器工作在 Spring MVC 內(nèi)部。如果你的 OPTIONS 請(qǐng)求因?yàn)槟承┌踩渲没驒?quán)限校驗(yàn)沒(méi)能通過(guò)
DispatcherServlet的映射,攔截器可能根本不會(huì)執(zhí)行。這會(huì)導(dǎo)致預(yù)檢請(qǐng)求失敗,瀏覽器直接攔截掉后續(xù)的正式請(qǐng)求。
2. 為什么選擇過(guò)濾器的三大理由
① 執(zhí)行時(shí)機(jī)最早(最核心原因)
跨域配置本質(zhì)上是給 HTTP 響應(yīng)頭加上 Access-Control-Allow-Origin 等字段。
- 過(guò)濾器在整個(gè)過(guò)濾鏈的最前端。如果請(qǐng)求跨域失敗,直接在過(guò)濾器層級(jí)就“擋回去”或“處理掉”了,不會(huì)浪費(fèi)后續(xù)的業(yè)務(wù)邏輯資源(如數(shù)據(jù)庫(kù)連接、權(quán)限檢查)。
② 解決權(quán)限框架(Security/Shiro)的沖突
如果你的項(xiàng)目中使用了 Spring Security,它本身就是通過(guò)一系列過(guò)濾器實(shí)現(xiàn)的。
- 如果你把跨域放在攔截器里,由于攔截器的執(zhí)行晚于 Spring Security 的過(guò)濾器,Spring Security 會(huì)在攔截器生效前發(fā)現(xiàn)請(qǐng)求沒(méi)帶 Token 或不符合安全規(guī)則,直接返回 403。
- 此時(shí)瀏覽器因?yàn)闆](méi)收到跨域響應(yīng)頭,會(huì)報(bào)一個(gè)“CORS error”,而隱藏了真正的“403 Forbidden”錯(cuò)誤,導(dǎo)致前端無(wú)法準(zhǔn)確定位問(wèn)題。
③ 覆蓋范圍廣
過(guò)濾器是針對(duì) URL 模式攔截的。如果你的項(xiàng)目里既有 Spring MVC 的 Controller,又有一些原生的 Servlet,或者靜態(tài)資源,過(guò)濾器可以一把抓,統(tǒng)一處理所有資源的跨域問(wèn)題。
3. 實(shí)現(xiàn)代碼對(duì)比
過(guò)濾器方案(推薦)
這種方式利用 Spring 提供的 CorsFilter,通常配合 FilterRegistrationBean 使用,優(yōu)先級(jí)設(shè)為最高。
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*"); // 允許所有來(lái)源
config.addAllowedHeader("*"); // 允許所有Header
config.addAllowedMethod("*"); // 允許所有方法
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 確保在最前端執(zhí)行
return bean;
}總結(jié)
跨域選擇過(guò)濾器,是因?yàn)樗?strong>在業(yè)務(wù)邏輯和安全框架之前處理 OPTIONS 請(qǐng)求。就像在大樓的**正門口(過(guò)濾器)貼上“歡迎光臨”的告示,比等客人進(jìn)了辦公室(攔截器)**才說(shuō)歡迎要高效且穩(wěn)妥得多。
到此這篇關(guān)于SpringMvc(Interceptor,Filter)實(shí)現(xiàn)方案的文章就介紹到這了,更多相關(guān)SpringMvc Interceptor,Filter內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 淺談SpringMVC的攔截器(Interceptor)和Servlet 的過(guò)濾器(Filter)的區(qū)別與聯(lián)系 及SpringMVC 的配置文件
- 淺談SpringMVC中Interceptor和Filter區(qū)別
- SpringMVC的處理器攔截器HandlerInterceptor詳解
- SpringMVC中的ConversionServiceExposingInterceptor工具類解析
- SpringMVC中的ResourceUrlProviderExposingInterceptor詳解
- SpringMVC Interceptor攔截器使用教程
- springMVC攔截器HandlerInterceptor用法代碼示例
- 詳解SpringMVC中使用Interceptor攔截器
相關(guān)文章
Java8使用LocalDate計(jì)算日期實(shí)例代碼解析
這篇文章主要介紹了Java8使用LocalDate計(jì)算實(shí)例代碼解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
談?wù)勗贘ava發(fā)送郵件中遇到的的問(wèn)題
本文介紹了在利用Java發(fā)送郵件過(guò)程中遇到的的兩個(gè)問(wèn)題,以及如何解決這兩個(gè)問(wèn)題。如果大家也遇到了這些問(wèn)題,可以來(lái)參考借鑒。2016-08-08
Java HashMap源碼及并發(fā)環(huán)境常見(jiàn)問(wèn)題解決
這篇文章主要介紹了Java HashMap源碼及并發(fā)環(huán)境常見(jiàn)問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
新手場(chǎng)景Java線程相關(guān)問(wèn)題及解決方案
這篇文章主要介紹了新手場(chǎng)景Java線程相關(guān)問(wèn)題及解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
SpringBoot頂層接口實(shí)現(xiàn)類注入項(xiàng)目的方法示例
本文主要介紹了SpringBoot頂層接口實(shí)現(xiàn)類注入項(xiàng)目的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
Spring生命周期回調(diào)與容器擴(kuò)展詳解
這篇文章主要介紹了Spring生命周期回調(diào)與容器擴(kuò)展詳解,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-12-12
WebUploader客戶端批量上傳圖片 后臺(tái)使用springMVC
這篇文章主要為大家詳細(xì)介紹了WebUploader客戶端批量上傳圖片,后臺(tái)使用springMVC接收實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-09-09
SpringBoot整合Spring?Security過(guò)濾器鏈加載執(zhí)行流程源碼分析(最新推薦)
Spring?Boot?對(duì)于?Spring?Security?提供了自動(dòng)化配置方案,可以使用更少的配置來(lái)使用?Spring?Security,這篇文章主要介紹了SpringBoot整合Spring?Security過(guò)濾器鏈加載執(zhí)行流程源碼分析,需要的朋友可以參考下2023-02-02
Java之SpringCloudAlibaba Sentinel組件案例講解
這篇文章主要介紹了Java之SpringCloudAlibaba Sentinel組件案例講解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

