Spring Boot 3 中 WebFilter 的執(zhí)行順序流程分析
理解并控制 WebFilter 的執(zhí)行順序?qū)τ跇嫿深A測、行為正確的 Web 應用至關重要。 本文詳細說明在 Spring Boot 3 中如何管理這些過濾器的執(zhí)行流程。
1. 默認執(zhí)行順序
- 核心規(guī)則: 當開發(fā)者未顯式指定任何順序時,所有
WebFilter實例的默認順序值被統(tǒng)一設置為Ordered.LOWEST_PRECEDENCE(其數(shù)值等于Integer.MAX_VALUE),這意味著它們默認擁有最低的優(yōu)先級,將在所有顯式指定了順序的過濾器之后執(zhí)行。 - 默認行為的影響: 在此默認順序值下,多個過濾器的實際執(zhí)行順序由 Spring 容器中 Bean 的注冊順序 決定。這個順序可能受到諸如類路徑掃描(
@ComponentScan)順序或@Bean配置方法在配置類中的聲明順序等因素的影響。這種行為本質(zhì)上是不可靠的,因為微小的代碼變動或依賴更新都可能導致順序意外改變,不應依賴于此進行關鍵邏輯控制。
2. 顯式控制順序的方法
為了確保執(zhí)行順序的確定性和可預測性,Spring 提供了兩種主要機制來顯式定義 WebFilter 的優(yōu)先級。
2.1 使用@Order注解
通過在過濾器類上添加 @Order 注解并指定一個整數(shù)值,可以清晰定義其順序。值越小,表示優(yōu)先級越高,在請求處理階段越早執(zhí)行。
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@Component
@Order(1) // 明確指定順序值為1(高優(yōu)先級)
public class FilterA implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
System.out.println("FilterA (Order=1) - Before Logic"); // 在執(zhí)行業(yè)務邏輯前
return chain.filter(exchange) // 將請求傳遞到鏈中的下一個過濾器或處理器
.then(Mono.fromRunnable(() ->
System.out.println("FilterA (Order=1) - After Logic"))); // 在業(yè)務邏輯執(zhí)行后和響應發(fā)送前
}
}2.2 實現(xiàn)Ordered接口
讓過濾器類實現(xiàn) Ordered 接口并重寫 getOrder() 方法是另一種等效且常用的方式。這種方式同樣遵循數(shù)值越小優(yōu)先級越高的原則。
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@Component
public class FilterB implements WebFilter, Ordered { // 同時實現(xiàn)WebFilter和Ordered接口
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
System.out.println("FilterB (Order=2) - Before Logic");
return chain.filter(exchange)
.then(Mono.fromRunnable(() ->
System.out.println("FilterB (Order=2) - After Logic")));
}
@Override
public int getOrder() { // 實現(xiàn)Ordered接口要求的方法,返回定義的順序值
return 2; // 顯式定義順序值為2
}
}3. 執(zhí)行順序規(guī)則
Spring WebFlux 框架對 WebFilter 鏈的執(zhí)行遵循明確的規(guī)則,區(qū)分請求處理(正向)和響應處理(反向)兩個階段:
- 正向流程(請求處理階段):
當請求進入時,框架會按順序值 從小到大(即優(yōu)先級從高到低)依次調(diào)用每個WebFilter的filter方法中的chain.filter(exchange)之前的代碼(即 “Before” 部分)。例如:@Order(1)→@Order(2)→ … →@Order(n)。 - 反向流程(響應處理階段):
當業(yè)務邏輯處理完畢,開始構建響應并向上返回時,框架會按順序值 從大到小(即優(yōu)先級從低到高)依次執(zhí)行每個WebFilter的filter方法中chain.filter(exchange).then(...)里面的回調(diào)代碼(即 “After” 部分)。例如:@Order(n)→ … →@Order(2)→@Order(1)。
3.1 示例輸出
結(jié)合 FilterA (Order=1) 和 FilterB (Order=2) 的代碼,執(zhí)行流程的日志輸出清晰地展示了上述規(guī)則:
FilterA (Order=1) - Before Logic // 最高優(yōu)先級(1)最先處理請求 FilterB (Order=2) - Before Logic // 次高優(yōu)先級(2)接著處理請求 ... (執(zhí)行業(yè)務控制器邏輯) ... // 實際業(yè)務處理 FilterB (Order=2) - After Logic // 次高優(yōu)先級(2)最先處理響應(反向) FilterA (Order=1) - After Logic // 最高優(yōu)先級(1)最后處理響應(反向)
4. 特殊情況:相同順序值
- 行為規(guī)則: 如果兩個或多個
WebFilter被顯式或隱式地賦予了相同的順序值(例如都使用@Order(5)或都未指定而使用默認值Integer.MAX_VALUE),則它們的執(zhí)行順序(包括正向和反向階段)將退回到由 Spring 容器中 Bean 的注冊順序 決定,這通常等同于類加載順序或@Bean/@Component的聲明或掃描順序。 - 潛在風險與建議: 由于這種順序在特定環(huán)境下可能不穩(wěn)定,強烈建議開發(fā)者為所有需要特定執(zhí)行位置的過濾器顯式分配唯一且有意義的順序值,避免依賴默認順序或沖突的順序值帶來的不確定性。
5. 總結(jié)
| 控制方式 | 實現(xiàn)示例 | 執(zhí)行順序規(guī)則 |
|---|---|---|
@Order 注解 | @Order(1) 標注在 WebFilter 實現(xiàn)類上 | 數(shù)值越小,在請求階段越早執(zhí)行 |
實現(xiàn) Ordered 接口 | getOrder() 方法返回具體數(shù)值 (如 2) | 數(shù)值越小,在請求階段越早執(zhí)行 |
| 未指定順序 | 無注解或接口實現(xiàn),默認 Integer.MAX_VALUE | 最后執(zhí)行,具體順序不穩(wěn)定 |
最佳實踐推薦:
- 始終顯式指定順序: 對于任何有依賴關系或執(zhí)行位置要求的
WebFilter,務必使用@Order注解或?qū)崿F(xiàn)Ordered接口來顯式定義其順序值(例如@Order(100),@Order(200))。 - 規(guī)劃順序值范圍: 為不同類型的過濾器預留順序值區(qū)間(如認證用 0-99,日志用 100-199,安全后處理用 200-299),提升可讀性和可維護性。
- 避免順序沖突: 確保關鍵過濾器的順序值唯一,防止因相同順序值導致的不確定行為。
遵循這些實踐能顯著增強過濾器行為的可預測性和應用的健壯性。
到此這篇關于Spring Boot 3 中 WebFilter 的執(zhí)行順序流程分析的文章就介紹到這了,更多相關Spring Boot WebFilter 執(zhí)行順序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java爬蟲實現(xiàn)爬取京東上的手機搜索頁面 HttpCliient+Jsoup
下面小編就為大家分享一篇Java爬蟲實現(xiàn)爬取京東上的手機搜索頁面 HttpCliient+Jsoup,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11
SpringMVC中利用@InitBinder來對頁面數(shù)據(jù)進行解析綁定的方法
本篇文章主要介紹了SpringMVC中利用@InitBinder來對頁面數(shù)據(jù)進行解析綁定的方法,非常具有實用價值,需要的朋友可以參考下2018-03-03

