WebFlux請求處理流程
下面是spring mvc的請求處理流程
具體步驟:
-
第一步:發起請求到前端控制器(DispatcherServlet)
-
第二步:前端控制器請求HandlerMapping查找 Handler (可以根據xml配置、注解進行查找)
匹配條件包括:請求路徑、請求方法、header信息等 -
第三步:處理器映射器HandlerMapping向前端控制器返回Handler,HandlerMapping會把請求映射為HandlerExecutionChain對象(包含一個Handler處理器(頁面控制器)對象,多個HandlerInterceptor攔截器對象),通過這種策略模式,很容易添加新的映射策略
HandlerInterceptor是請求路徑上的攔截器,需要自己實現這個接口以攔截請求,做一些對handler的前置和后置處理工作。 -
第四步:前端控制器調用處理器適配器去執行Handler
-
第五步:處理器適配器HandlerAdapter將會根據適配的結果去執行Handler
-
第六步:Handler執行完成給適配器返回ModelAndView
-
第七步:處理器適配器向前端控制器返回ModelAndView (ModelAndView是springmvc框架的一個底層對象,包括 Model和view)
-
第八步:前端控制器請求視圖解析器去進行視圖解析 (根據邏輯視圖名解析成真正的視圖(jsp)),通過這種策略很容易更換其他視圖技術,只需要更改視圖解析器即可
-
第九步:視圖解析器向前端控制器返回View
-
第十步:前端控制器進行視圖渲染 (視圖渲染將模型數據(在ModelAndView對象中)填充到request域)
-
第十一步:前端控制器向用戶響應結果
圖解:注解驅動請求的webflux請求處理流程
我們可以對比SpringMVC的請求流程圖對比來看
我們可以看到,處理流程基本一樣,有以下主要的點不同
- 處理核心
- WebFlux--
DispatcherHandler
- SpringMvc--
DispatcherServlet
- WebFlux--
- 返回值處理器
- WebFlux--
HandlerResultHandler
- SpringMvc--
HandlerMethodReturnValueHandler
- WebFlux--
- 內容協商配置器
- WebFlux--
RequestedContentTypeResolverBuilder
- SpringMvc--
ContentNegotiationConfigurer
- WebFlux--
還有很多就不一一例舉了,想知道核心組件對比結果的同學,可以看下圖。注意很多圖上的組件名稱相同,但是包的位置是不同的,所以大家要注意區分,不要弄混了。
Web MVC VS. WebFlux 核心組件對比
WebFlux 都有哪些核心組件
Spring WebFlux 包含多個核心組件,它們共同構成了完整的響應式 Web 應用框架。下面是一些主要的核心組件:
-
DispatcherHandler:這是 WebFlux 的中央調度器,類似于 Spring MVC 中的 DispatcherServlet。它負責發現和調度 HTTP 請求處理器(handlers),并處理請求映射、調用和結果處理。
-
HandlerMapping:這個接口用于將請求映射到對應的處理器(handler)。它在應用程序上下文中被檢測到,并用于確定請求應該由哪個處理器處理。
-
HandlerAdapter:這個接口幫助 DispatcherHandler 調用任何類型的處理器,而不需要關心具體的調用方式。它為不同的處理器提供了調用策略。
-
HandlerResultHandler:這個接口處理處理器調用后的結果,并生成最終的響應。它負責將處理器的結果轉換為客戶端可以接收的格式。
-
WebFilter:WebFilter 接口定義了一組過濾器,這些過濾器可以對請求和響應進行預處理和后處理。
-
ServerWebExchange:這個類封裝了 HTTP 請求和響應的所有信息,例如請求頭、請求體、URI、參數等。
-
ServerHttpRequest 和 ServerHttpResponse:這兩個類分別代表服務器接收的 HTTP 請求和發送的 HTTP 響應。
-
WebSession:用于管理特定客戶端的會話信息。
-
Reactive Streams:WebFlux 基于 Reactive Streams 規范,使用非阻塞背壓機制來處理數據流。
-
Reactor 庫:作為 Spring 5 的反應式編程基礎,Reactor 提供了非阻塞的編程模型和工具,包括 Flux 和 Mono 等反應式類型。
-
WebClient:這是 Spring 5 中引入的非阻塞、支持響應式流的 HTTP 客戶端,用于與其它服務進行通信。
-
Spring Data Reactive:提供對響應式數據訪問的支持,例如 Reactive Repositories。
-
Spring Security Reactive:提供對響應式安全訪問控制的支持。
-
HttpHandler:定義了最低級別的反應式 HTTP 請求處理合同,作為不同運行時之間的共同基礎。
-
ContextPathCompositeHandler:允許在不同的上下文路徑上注冊多個應用程序。
這些組件共同工作,為開發人員提供了一個強大且靈活的響應式 Web 應用開發平臺。通過這些組件,開發者可以構建出能夠高效處理大量并發請求的應用程序。下面針對這些組件,V 哥將一一詳細介紹核心源碼的實現過程,幫助兄弟們徹底理解。
1. DispatcherHandler
DispatcherHandler 是 Spring WebFlux 的核心組件,它的作用類似于 Spring MVC 中的 DispatcherServlet。它負責將傳入的 HTTP 請求分發給相應的處理器(handler),并處理請求的映射、調用和結果處理。以下是對 DispatcherHandler 組件源碼實現邏輯和步驟的詳細分析:
初始化過程
-
ApplicationContextAware 實現:DispatcherHandler 實現了 ApplicationContextAware 接口,這意味著它可以訪問到 Spring 應用上下文中的 Bean。
-
HandlerMapping、HandlerAdapter 和 HandlerResultHandler 的初始化:DispatcherHandler 在初始化時會查找 Spring 應用上下文中所有的 HandlerMapping、HandlerAdapter 和 HandlerResultHandler 并初始化它們。
protected void initStrategies(ApplicationContext context) {// ... 省略部分代碼 ...this.handlerMappings = ...;this.handlerAdapters = ...;this.resultHandlers = ...;}
請求處理過程
-
獲取 HandlerMappings:DispatcherHandler 會通過 handlerMappings 來查找能夠處理當前請求的 HandlerMapping。
-
映射請求到 Handler:使用找到的 HandlerMapping 將請求映射到具體的處理器(可能是一個 @Controller 方法或者一個 RouterFunction)。
-
調用 Handler:一旦找到處理器,DispatcherHandler 會使用適當的 HandlerAdapter 來調用處理器。
-
處理結果:處理器的執行結果會被 HandlerResultHandler 處理,生成響應。
核心方法:handle
DispatcherHandler 的核心方法是 handle,它定義了請求處理的流程:
public Mono<Void> handle(ServerWebExchange exchange) {// 檢查是否初始化了 handlerMappingsif (this.handlerMappings == null) {return createNotFoundError();}// 使用 handlerMappings 來查找 handlerreturn Flux.fromIterable(this.handlerMappings).concatMap(mapping -> mapping.getHandler(exchange)).next() // 獲取第一個 handler.switchIfEmpty(createNotFoundError()) // 如果沒有找到 handler,返回錯誤.flatMap(handler -> invokeHandler(exchange, handler)) // 調用 handler.flatMap(result -> handleResult(exchange, result)); // 處理結果
}
錯誤處理
- createNotFoundError:如果沒有找到合適的處理器,DispatcherHandler 會創建一個表示 "Not Found" 的響應。
其他組件的協同工作
- HandlerMapping:負責將請求 URL 映射到具體的處理器。
- HandlerAdapter:負責調用具體的處理器,Spring WebFlux 支持多種類型的處理器,HandlerAdapter 使得 DispatcherHandler 無需關心具體的調用細節。
- HandlerResultHandler:負責處理處理器的返回值,并將其轉換為 HTTP 響應。
DispatcherHandler 的設計使得它非常靈活,可以很容易地擴展新的 HandlerMapping、HandlerAdapter 或 HandlerResultHandler 來支持不同的處理器類型和返回類型。
以上就是 DispatcherHandler 組件的源碼實現邏輯和步驟的分析。通過這種方式,Spring WebFlux 能夠以非阻塞的方式處理 Web 請求,提高應用的性能和可伸縮性。
2. HandlerMapping
HandlerMapping 是 Spring WebFlux 中的一個接口,它定義了將請求映射到處理器(handler)的邏輯。HandlerMapping 的實現類負責根據請求的類型、URL 模式等信息來確定哪個具體的處理器應該處理當前的請求。以下是對 HandlerMapping 組件的源碼實現邏輯和步驟的詳細分析:
HandlerMapping 接口定義
HandlerMapping 接口定義了以下關鍵方法:
public interface HandlerMapping {Mono<Object> getHandler(ServerWebExchange exchange);void afterPropertiesSet();
}
- getHandler:根據給定的 ServerWebExchange 對象,返回一個 Mono 對象,該 Mono 完成時包含請求的處理器。
- afterPropertiesSet:在所有屬性都設置之后調用,允許 HandlerMapping 實現進行初始化。
主要實現類
Spring WebFlux 提供了幾個 HandlerMapping 的實現類,主要包括:
-
RequestMappingHandlerMapping:處理基于注解的映射,例如 @RequestMapping、@GetMapping 等。
-
RouterFunctionMapping:處理基于 RouterFunction 的函數式路由。
-
SimpleUrlHandlerMapping:處理簡單的 URL 到對象的映射。
RequestMappingHandlerMapping 源碼分析
RequestMappingHandlerMapping 是最常用的 HandlerMapping 實現之一,下面是它的一些關鍵實現邏輯:
-
注冊和解析:在初始化時,RequestMappingHandlerMapping 會掃描所有的 beans,查找帶有 @RequestMapping 注解的方法,并注冊這些方法作為請求的處理器。
-
映射處理:RequestMappingHandlerMapping 使用 Pattern 對象來存儲和匹配 URL 模式。
-
getHandler 方法實現:
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {String lookupPath = getPath(exchange);return getHandlerInternal(exchange).filter(h -> matchesRoute(lookupPath, h)).switchIfEmpty(Mono.defer(() -> getBestMatchingHandler(lookupPath, exchange)));
}
- getPath:從 ServerWebExchange 中提取請求路徑。
- getHandlerInternal:返回一個包含所有注冊處理器的 Mono。
- filter 和 matchesRoute:檢查處理器是否與請求路徑匹配。
- getBestMatchingHandler:如果沒有找到精確匹配的處理器,嘗試找到最佳匹配的處理器。
映射匹配邏輯
映射匹配邏輯通常涉及以下步驟:
-
路徑匹配:檢查請求的路徑是否與注冊的 URL 模式匹配。
-
請求方法匹配:如果 URL 模式匹配,進一步檢查請求的方法(GET、POST 等)是否與處理器支持的方法匹配。
-
參數條件匹配:檢查請求是否包含處理器所需的參數。
-
頭信息匹配:檢查請求頭是否滿足特定的條件。
-
消費和產生媒體類型匹配:檢查請求的 Accept 頭和 Content-Type 是否與處理器支持的媒體類型匹配。
性能優化
RequestMappingHandlerMapping 還實現了一些性能優化措施,例如緩存匹配的 URL 模式,以減少重復的模式匹配操作。
小結一下
HandlerMapping 組件是 Spring WebFlux 請求處理流程中的關鍵部分,它負責將進入的請求映射到正確的處理器。通過使用不同的 HandlerMapping 實現,Spring WebFlux 支持靈活的請求映射策略,以適應不同的應用場景。
3. HandlerAdapter
HandlerAdapter 接口在 Spring WebFlux 中扮演著至關重要的角色,它的作用是將 DispatcherHandler 找到的處理器(handler)適配到具體的執行邏輯上。HandlerAdapter 使得 DispatcherHandler 無需關心具體的處理器類型,只需要通過 HandlerAdapter 來調用處理器即可。以下是對 HandlerAdapter 組件的源碼實現邏輯和步驟的詳細分析:
HandlerAdapter 接口定義
HandlerAdapter 接口定義了以下關鍵方法:
public interface HandlerAdapter {boolean supports(Object handler);Mono<Void> handle(ServerWebExchange exchange, Object handler, Object... args);
}
- supports:檢查給定的處理器是否被當前 HandlerAdapter 支持。
- handle:調用處理器,并返回一個 Mono
<Void>
?對象,表示異步的調用過程。
主要實現類
Spring WebFlux 提供了幾個 HandlerAdapter 的實現類,主要包括:
-
RequestMappingHandlerAdapter:支持基于注解的控制器方法,如帶有 @RequestMapping 注解的方法。
-
HttpHandlerAdapter:支持 HttpHandler 接口的處理器。
-
ControllerEndpointHandlerAdapter:支持 ControllerEndpoint 接口的處理器,通常用于 WebFlux 函數式編程。
-
RouterFunctionHandlerAdapter:支持 RouterFunction 接口,用于函數式路由。
RequestMappingHandlerAdapter 源碼分析
RequestMappingHandlerAdapter 是最常用的 HandlerAdapter 實現之一,下面是它的一些關鍵實現邏輯:
- 支持性檢查:supports 方法檢查給定的處理器是否是 Controller 或者 RequestMapping 注解的方法。
@Override
public boolean supports(Object handler) {return (handler instanceof HandlerFunction) ||(handler instanceof Controller) ||AnnotationUtils.findAnnotation(handler.getClass(), RequestMapping.class) != null;
}
調用處理器:handle 方法調用處理器,并處理返回值。
@Overridepublic Mono<Void> handle(ServerWebExchange exchange, Object handler) {// 調用具體的處理器return ((HandlerFunction<ServerResponse>) handler).handle(exchange);}
調用處理器的邏輯
調用處理器的邏輯通常涉及以下步驟:
-
參數解析:解析請求中的參數,并將其轉換為方法參數。
-
調用方法:調用處理器的方法,并將解析后的參數傳遞給方法。
-
處理返回值:處理方法的返回值,將其轉換為響應。
-
異步處理:如果處理器返回的是 Mono 或 Flux,HandlerAdapter 需要處理這些異步結果。
錯誤處理
HandlerAdapter 還負責處理調用過程中的異常,將異常轉換為合適的響應。
小結一下
HandlerAdapter 組件是 Spring WebFlux 請求處理流程中的關鍵部分,它解耦了 DispatcherHandler 和具體的處理器實現。通過使用不同的 HandlerAdapter 實現,Spring WebFlux 支持了多種類型的處理器,包括基于注解的控制器、函數式路由以及 HttpHandler 接口的實現。這種設計提高了框架的靈活性和可擴展性。
4. HandlerResultHandler
HandlerResultHandler 組件在 Spring WebFlux 中負責處理由 HandlerAdapter 調用處理器后返回的結果。它將這些結果轉換為客戶端可以接收的 HTTP 響應。以下是對 HandlerResultHandler 組件的源碼實現邏輯和步驟的詳細分析:
HandlerResultHandler 接口定義
HandlerResultHandler 接口定義了以下關鍵方法:
public interface HandlerResultHandler {boolean supports(HandlerResult result);Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result);
}
- supports:檢查給定的 HandlerResult 是否被當前 HandlerResultHandler 支持。
- handleResult:處理 HandlerResult,生成響應并返回一個 Mono
<Void>
?對象,表示異步的處理過程。
主要實現類
Spring WebFlux 提供了幾個 HandlerResultHandler 的實現類,主要包括:
- ServerResponseResultHandler:處理 ServerResponse 類型的返回值。
- ResponseEntityResultHandler:處理 ResponseEntity 類型的返回值。
- ModelAndViewResultHandler:處理 ModelAndView 類型的返回值,通常用于視圖渲染。
ServerResponseResultHandler 源碼分析
ServerResponseResultHandler 是處理 ServerResponse 類型結果的 HandlerResultHandler 實現:
- 支持性檢查:supports 方法檢查 HandlerResult 是否包含 ServerResponse 對象。
@Override
public boolean supports(HandlerResult result) {return result.getReturnValue() instanceof ServerResponse;
}
- 處理結果:handleResult 方法處理 ServerResponse 對象,并生成響應。
@Overridepublic Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {ServerResponse response = (ServerResponse) result.getReturnValue();return response.writeTo(exchange, result.isCommitted());}
處理結果的邏輯
處理結果的邏輯通常涉及以下步驟:
-
獲取返回值:從 HandlerResult 中獲取處理器的返回值。
-
檢查類型:根據返回值的類型,選擇合適的處理邏輯。
-
生成響應:將返回值轉換為 HTTP 響應。例如,ServerResponse 已經包含了響應的狀態碼、頭信息和體。
-
異步處理:如果返回值是異步的(如 Mono 或 Flux),則需要處理這些異步結果。
-
寫入響應:將生成的響應寫入到 ServerWebExchange 中。
錯誤處理
HandlerResultHandler 還負責處理結果處理過程中的異常,將異常轉換為合適的響應。
小結一下
HandlerResultHandler 組件是 Spring WebFlux 請求處理流程中的關鍵部分,它負責將處理器的返回值轉換為 HTTP 響應。通過使用不同的 HandlerResultHandler 實現,Spring WebFlux 支持了多種返回值類型,包括 ServerResponse、ResponseEntity 和 ModelAndView。這種設計提高了框架的靈活性和可擴展性,允許開發者以不同的方式處理響應結果。
HandlerResultHandler 的實現通常需要考慮響應的異步特性,確保即使在異步流的情況下也能正確地生成和發送響應。此外,它還需要與 ServerWebExchange 緊密協作,以便訪問和操作請求和響應的上下文信息。
5. WebFilter
WebFilter 接口是 Spring WebFlux 中用于攔截和處理 Web 請求和響應的組件。它允許開發者在請求到達具體的處理器之前或之后,對請求或響應進行額外的處理,例如日志記錄、安全性檢查、跨域處理等。以下是對 WebFilter 組件的源碼實現邏輯和步驟的詳細分析:
WebFilter 接口定義
WebFilter 接口定義了以下關鍵方法:
public interface WebFilter {Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
}
- filter:對給定的 ServerWebExchange 對象進行處理,并通過 WebFilterChain 調用鏈中的下一個 WebFilter 或最終的處理器。
過濾器鏈
在 Spring WebFlux 中,WebFilter 通常會被組織成一個過濾器鏈,每個 WebFilter 都可以決定是繼續過濾請求還是將請求傳遞給鏈中的下一個 WebFilter。這種鏈式調用模式使得過濾器的執行順序非常重要。
主要實現類
Spring WebFlux 提供了一些內置的 WebFilter 實現類,例如:
- ServerHttpSecurity:用于安全性檢查。
- CorsFilter:用于處理跨源資源共享(CORS)。
- WebFilterChain:代表過濾器鏈的上下文,允許調用鏈中的下一個 WebFilter。
過濾器鏈的構建
過濾器鏈通常在應用程序的配置中構建,例如使用 WebFilter 接口的實現類:
@Configuration
public class WebFluxConfig {@Beanpublic WebFilter myCustomFilter() {return (exchange, chain) -> {// 在這里可以對請求進行預處理return chain.filter(exchange).subscriberContext(ctx -> ctx.put("customKey", "customValue"));};}
}
WebFilter 的實現邏輯
實現 WebFilter 接口的 filter 方法通常涉及以下步驟:
-
預處理:在調用 chain.filter(exchange) 之前,對 ServerWebExchange 進行任何必要的預處理,例如修改請求頭、查詢參數等。
-
調用鏈:使用 WebFilterChain 的 filter 方法將請求傳遞給鏈中的下一個 WebFilter。這通常會返回一個 Mono
<Void>
,表示異步的過濾過程。 -
后處理:在 chain.filter(exchange) 完成后,對 ServerWebExchange 進行任何必要的后處理,例如修改響應頭、響應體等。
-
錯誤處理:處理在過濾過程中可能發生的異常,并決定是拋出新的錯誤、返回特定的響應或繼續過濾鏈。
異步處理
由于 filter 方法返回的是 Mono<Void>
,WebFilter 的實現需要考慮異步處理。這意味著在過濾過程中,可以返回異步的響應,而不會阻塞整個請求的處理。
小結一下
WebFilter 組件是 Spring WebFlux 中用于攔截和處理 Web 請求和響應的強大工具。通過實現 WebFilter 接口并構建過濾器鏈,開發者可以靈活地對請求和響應進行預處理和后處理,以及實現各種橫切關注點,如安全性、日志記錄、CORS 處理等。這種設計提高了應用程序的模塊性和可維護性,同時保持了非阻塞和異步的特性。
6. ServerWebExchange
ServerWebExchange 是 Spring WebFlux 中的一個核心組件,它封裝了 HTTP 請求和響應的上下文信息,為 Web 服務器和應用程序之間提供了一個交互的接口。以下是對 ServerWebExchange 組件的源碼實現邏輯和步驟的詳細分析:
ServerWebExchange 接口定義
ServerWebExchange 接口定義了對 HTTP 請求和響應的訪問和操作:
public interface ServerWebExchange {ServerHttpRequest getRequest();ServerHttpResponse getResponse();void beforeCommit();boolean isCommitted();void setCommitted(boolean committed);Context getContext();
}
- getRequest():返回當前的 ServerHttpRequest 對象,包含請求的詳細信息。
- getResponse():返回當前的 ServerHttpResponse 對象,用于構造響應。
- beforeCommit():在響應提交之前調用,允許進行一些清理或準備操作。
- isCommitted():檢查響應是否已經提交。
- setCommitted(boolean committed):設置響應是否提交的狀態。
- getContext():返回與當前交換關聯的 Context,用于存儲和傳遞附加信息。
核心屬性
ServerWebExchange 通常包含以下核心屬性:
- request:ServerHttpRequest 對象,封裝了 HTTP 請求的詳細信息,如頭信息、URI、方法等。
- response:ServerHttpResponse 對象,用于構造和發送 HTTP 響應。
- principal:可能包含當前請求的認證主體(Principal)。
- session:可能包含當前請求的會話信息。
- attributes:一個 Map,用于存儲與請求相關的屬性。
請求和響應的處理
ServerWebExchange 在請求和響應的處理中扮演著核心角色:
-
請求獲取:通過 getRequest() 方法獲取請求對象,訪問請求的各種信息。
-
響應構造:通過 getResponse() 方法獲取響應對象,構造響應的狀態碼、頭信息和響應體。
-
上下文管理:使用 Context 對象存儲和傳遞請求和響應過程中的附加信息。
-
提交管理:通過 beforeCommit()、isCommitted() 和 setCommitted() 方法管理響應的提交狀態。
-
過濾器鏈:在 WebFilter 的實現中,ServerWebExchange 對象在過濾器鏈中傳遞,每個過濾器都可以訪問和修改請求和響應。
異步處理
由于 WebFlux 是響應式的,ServerWebExchange 支持異步處理:
- 響應可以通過非阻塞的方式寫入,例如使用 ServerHttpResponse 的異步方法。
- 請求和響應的處理可以在不同的線程或事件循環中進行。
小結一下
ServerWebExchange 是 Spring WebFlux 中處理 HTTP 請求和響應的核心組件。它提供了一個統一的接口來訪問和操作請求和響應數據,同時支持異步非阻塞的處理方式。通過 ServerWebExchange,開發者可以在 Web 服務器和應用程序之間進行高效的數據交換和狀態管理,實現高性能的響應式 Web 應用。
ServerWebExchange 的實現通常需要考慮響應式的編程模型,確保在處理請求和構造響應時不會阻塞事件循環,從而充分利用 WebFlux 的性能優勢。此外,它還提供了豐富的上下文管理功能,使得在復雜的請求處理流程中,可以方便地存儲和傳遞附加信息。
7. ServerHttpRequest和ServerHttpResponse
ServerHttpRequest 和 ServerHttpResponse 是 Spring WebFlux 中的兩個核心接口,它們分別表示服務器接收的 HTTP 請求和發送的 HTTP 響應。以下是對這兩個組件的源碼實現邏輯和步驟的詳細分析:
ServerHttpRequest 接口定義
ServerHttpRequest 接口定義了對 HTTP 請求的訪問:
public interface ServerHttpRequest {URI getURI();HttpMethod getMethod();String getHeader(String headerName);MultiValueMap<String, String> getHeaders();DataBufferFactory bufferFactory();// 省略其他方法...
}
- getURI():返回請求的 URI。
- getMethod():返回 HTTP 方法(如 GET、POST 等)。
- getHeader(String headerName):根據名稱獲取請求頭的值。
- getHeaders():返回包含所有請求頭的 MultiValueMap。
- bufferFactory():返回用于創建數據緩沖區(DataBuffer)的工廠。
ServerHttpResponse 接口定義
ServerHttpResponse 接口定義了對 HTTP 響應的構造和發送:
public interface ServerHttpResponse {HttpStatusSeriesStatus.Series getStatusSeries();void setStatusCode(HttpStatus statusCode);String getHeader(String headerName);MultiValueMap<String, String> getHeaders();void setComplete();DataBufferFactory bufferFactory();Mono<Void> writeWith(Publisher<? extends DataBuffer> body);// 省略其他方法...
}
- getStatusSeries():返回響應的狀態碼系列(如 2xx、3xx 等)。
- setStatusCode(HttpStatus statusCode):設置 HTTP 狀態碼。
- getHeader(String headerName):根據名稱獲取響應頭的值。
- getHeaders():返回包含所有響應頭的 MultiValueMap。
- setComplete():標記響應為完成。
- writeWith(Publisher
<? extends DataBuffer> body)
:發送響應體。
請求和響應的處理
ServerHttpRequest 和 ServerHttpResponse 在處理 HTTP 請求和響應中扮演著核心角色:
-
請求信息獲取:通過 ServerHttpRequest 的方法獲取請求的 URI、方法、頭信息等。
-
響應構造:使用 ServerHttpResponse 的方法設置狀態碼、頭信息,并構造響應體。
-
數據緩沖區:通過 bufferFactory() 方法獲取 DataBufferFactory,用于創建和管理數據緩沖區。
-
異步發送:ServerHttpResponse 的 writeWith(Publisher
<? extends DataBuffer> body)
?方法支持異步發送響應體。 -
流式處理:支持以流式的方式讀取請求體和寫入響應體。
異步非阻塞
由于 WebFlux 是基于響應式編程模型的,ServerHttpRequest 和 ServerHttpResponse 支持異步非阻塞的操作:
- 請求體和響應體可以通過 Publisher
<DataBuffer>
?形式異步讀取和發送。 - 響應的發送不會阻塞事件循環。
小結一下
ServerHttpRequest 和 ServerHttpResponse 是 Spring WebFlux 中處理 HTTP 請求和響應的接口。它們提供了豐富的方法來訪問請求信息、構造響應,并支持異步非阻塞的操作。通過這兩個接口,開發者可以構建高性能、響應式的 Web 應用,充分利用現代硬件和軟件架構的優勢。
在實際應用中,開發者通常不需要直接實現這些接口,而是通過框架提供的實現類來操作請求和響應。這些實現類通常會與特定的運行時環境(如 Netty)集成,以提供高效的 I/O 操作。
8. WebSession
WebSession 組件在 Spring WebFlux 中用于表示和管理 Web 會話(session)。它提供了一種機制來存儲和檢索與特定用戶會話相關的數據。以下是對 WebSession 組件的源碼實現邏輯和步驟的詳細分析:
WebSession 接口定義
WebSession 接口定義了 Web 會話的基本操作:
public interface WebSession {String getId();Mono<WebSession> save();void invalidate();Map<String, Object> getAttributes();<T> T getAttribute(String name);<T> void setAttribute(String name, T value);default <T> Mono<T> getAttributeOrDefault(String name, Supplier<? extends T> defaultValue);// 省略其他方法...
}
- getId():獲取會話的唯一標識符。
- save():保存會話的更改。
- invalidate():使會話無效,相當于會話過期。
- getAttributes():獲取會話的所有屬性。
- getAttribute(String name):根據名稱獲取會話屬性。
- setAttribute(String name, T value):設置會話屬性。
WebSession 的實現邏輯
-
會話創建:WebSession 可以在請求處理過程中創建,通常與 ServerWebExchange 關聯。
-
屬性管理:會話屬性存儲在 getAttributes() 返回的 Map 中,允許存儲和檢索用戶特定的信息。
-
異步保存:save() 方法異步保存會話更改,這可能涉及將更改寫入底層存儲。
-
會話失效:invalidate() 方法用于使會話無效,確保會話數據不再可用。
-
會話 ID 管理:每個 WebSession 實例都有一個唯一的 id,用于標識特定的用戶會話。
-
默認值獲取:getAttributeOrDefault() 方法提供了一種便捷的方式來獲取屬性值,如果屬性不存在,則返回默認值。
會話的存儲和檢索
WebSession 的實現通常需要考慮以下方面:
- 存儲機制:會話數據可以存儲在不同的介質中,例如內存、數據庫或分布式緩存。
- 并發處理:在多線程或異步環境中,需要確保會話數據的一致性。
- 會話超時:實現會話超時邏輯,自動使過期的會話無效。
會話的創建和綁定
在請求處理過程中,WebSession 可以被創建和綁定到 ServerWebExchange:
ServerWebExchange exchange = ...;
Mono<WebSession> sessionMono = exchange.getSession();
sessionMono.flatMap(session -> {// 使用會話return session.save();
});
小結一下
WebSession 組件是 Spring WebFlux 中用于管理 Web 會話的接口。它提供了一種靈活的方式來存儲和檢索與用戶會話相關的數據,同時支持異步操作和多種存儲選項。通過 WebSession,開發者可以輕松實現用戶會話跟蹤和管理,構建具有個性化用戶體驗的 Web 應用。
在實際應用中,開發者可以根據需要選擇不同的會話存儲實現,例如使用 Spring Session 項目提供的多種存儲解決方案,包括 Redis、Hazelcast、JDBC 等。這些實現通常會處理會話的創建、保存、失效等邏輯,并與 WebSession 接口進行集成。
9. Reactive Streams
Reactive Streams 是一個規范,它定義了異步流處理的接口和行為,以便在不同的庫和框架之間實現互操作性。Spring WebFlux 作為響應式編程的一部分,遵循 Reactive Streams 規范。以下是對 Reactive Streams 組件的源碼實現邏輯和步驟的詳細分析:
Reactive Streams 核心接口
Reactive Streams 規范定義了以下幾個核心接口:
Publisher<T>
:發布者,表示可以產生數據的源頭。Subscriber<T>
:訂閱者,表示接收并處理數據的消費者。Subscription
:訂閱關系,用于管理數據的請求和發送。Processor<T,R>
:處理器,是 Publisher 和 Subscriber 的結合體。
Publisher 接口
Publisher 接口是 Reactive Streams 的核心,它定義了如何將數據推送給 Subscriber:
public interface Publisher<T>
?{
void subscribe(Subscriber<? super T>
?s);
}
subscribe(`Subscriber<? super T> s`):允許 Subscriber 訂閱 Publisher。
Subscriber 接口
Subscriber 接口定義了如何處理從 Publisher 接收到的數據:
public interface Subscriber<T> {void onSubscribe(Subscription s);void onNext(T t);void onError(Throwable t);void onComplete();
}
- onSubscribe(Subscription s):當 Subscriber 訂閱 Publisher 后被調用,Subscription 用于控制數據流。
- onNext(T t):接收到新數據時調用。
- onError(Throwable t):發生錯誤時調用。
- onComplete():數據流結束時調用。
Subscription 接口
Subscription 接口用于管理 Subscriber 和 Publisher 之間的數據流:
public interface Subscription {void request(long n);void cancel();
}
- request(long n):請求 Publisher 發送指定數量的數據項。
- cancel():取消訂閱,停止接收數據。
Processor 接口
Processor 是 Publisher 和 Subscriber 的結合體,可以接收數據并產生新的數據流:
public interface Processor<T, R> extends Subscriber<T>, Publisher<R> {// 繼承自 Subscriber 和 Publisher 的方法
}
源碼實現邏輯
- 數據流創建:使用 Publisher 創建數據流。
- 訂閱機制:Subscriber 通過調用 Publisher 的 subscribe 方法訂閱數據流。
- 數據請求:Subscriber 使用 Subscription 的 request 方法控制數據的接收速率。
- 數據推送:Publisher 根據 Subscriber 的請求發送數據項給 Subscriber。
- 錯誤和完成處理:Publisher 在發生錯誤或數據流結束時,分別調用 Subscriber 的 onError 或 onComplete 方法。
- 取消訂閱:Subscriber 可以通過調用 Subscription 的 cancel 方法取消訂閱。
步驟
- 初始化:創建 Publisher 和 Subscriber 對象。
- 訂閱:Subscriber 調用 Publisher 的 subscribe 方法。
- 處理訂閱:Publisher 調用 Subscriber 的 onSubscribe 方法,傳入 Subscription 對象。
- 請求數據:Subscriber 使用 Subscription 請求數據。
- 發送數據:Publisher 根據請求發送數據給 Subscriber。
- 完成或錯誤:Publisher 在數據發送完畢后調用 onComplete,或在發生錯誤時調用 onError。
小結一下
Reactive Streams 規范提供了一種異步、非阻塞的數據處理模型,Spring WebFlux 通過實現這些接口,支持響應式編程。這種模型允許系統更有效地處理并發數據流,提高性能和可伸縮性。開發者可以利用 Reactive Streams 規范提供的接口和機制,構建高效、彈性的響應式應用程序。
10. Reactor 庫
Reactor 是一個基于 Reactive Streams 規范的庫,用于構建異步、非阻塞的響應式應用程序。它是 Spring WebFlux 的反應式編程基礎。以下是對 Reactor 庫組件的源碼實現邏輯和步驟的詳細分析:
Reactor 核心組件
Reactor 提供了以下核心組件:
- Flux:代表一個包含 0 到 N 個元素的響應式序列。
- Mono:代表一個包含 0 到 1 個元素的響應式序列。
- Scheduler:用于控制并發和執行異步操作的調度器。
Flux 和 Mono 的實現邏輯
-
數據流創建:通過靜態方法(如 Flux.just(), Mono.just())或構造函數創建 Flux 或 Mono 實例。
-
操作符:Reactor 提供了豐富的操作符來處理數據流,例如 map、flatMap、filter 等。
-
訂閱機制:通過 subscribe() 方法訂閱數據流,并提供 Subscriber 來接收數據。
-
數據請求:使用 request() 方法控制數據的請求數量。
-
數據推送:數據通過 onNext() 方法推送給訂閱者。
-
錯誤和完成處理:通過 onError() 和 onComplete() 方法處理數據流的錯誤和完成事件。
Scheduler 的實現邏輯
-
調度器創建:創建 Scheduler 實例,例如使用 Schedulers.parallel() 創建并行調度器。
-
任務調度:使用 schedule() 方法調度任務,返回 Mono 或 Flux。
-
并發控制:Scheduler 可以控制任務的并發執行,例如限制并發數量。
-
異步執行:任務在非阻塞的線程池中異步執行。
源碼實現步驟
-
定義數據源:創建 Flux 或 Mono 實例作為數據源。
-
應用操作符:使用操作符對數據流進行轉換、過濾或組合。
-
錯誤處理:使用 onErrorResume() 或 doOnError() 等操作符處理錯誤。
-
背壓管理:使用 onBackpressureBuffer() 或 onBackpressureDrop() 等操作符處理背壓。
-
訂閱和消費:調用 subscribe() 方法訂閱數據流,并提供 Subscriber 來消費數據。
-
調度任務:使用 Scheduler 調度異步任務。
-
資源清理:使用 dispose() 方法在不再需要時釋放資源。
小結一下
Reactor 庫通過 Flux、Mono 和 Scheduler 等組件,提供了一種強大的方式來構建響應式應用程序。它遵循 Reactive Streams 規范,支持異步非阻塞的數據流處理。Reactor 的操作符豐富,可以輕松實現復雜的數據處理邏輯。同時,它還提供了靈活的并發控制和調度機制,以適應不同的應用場景。
Reactor 的設計哲學是提供聲明式的數據處理能力,讓開發者能夠以一種直觀和靈活的方式構建響應式系統。通過 Reactor,開發者可以充分利用現代硬件的多核特性,提高應用程序的性能和可伸縮性。
11. WebClient
WebClient 是 Spring WebFlux 中用于發起 HTTP 請求的非阻塞響應式客戶端。它允許你以聲明式的方式構建請求并處理響應。以下是對 WebClient 組件的源碼實現邏輯和步驟的詳細分析:
WebClient 接口定義
WebClient 提供了發起請求的方法:
public interface WebClient {default URI uri() {return URI.create(this.baseUrl);}<T> Mono<T> getForObject(String url, Class<T> responseType, Object... uriVariables);<T> Flux<T> getForFlux(String url, Class<T> elementType, Object... uriVariables);// 其他 HTTP 方法的重載,例如 postForObject, putForObject 等
}
- uri():返回基礎 URI。
- getForObject(String url, ...):發起 GET 請求并期望獲取對象響應。
- getForFlux(String url, ...):發起 GET 請求并期望獲取元素流響應。
WebClient.Builder 構建器
WebClient 的實例是通過 WebClient.Builder 構建的:
public final class WebClient.Builder {private final String baseUrl;public Builder(String baseUrl) {this.baseUrl = baseUrl;}public WebClient build() {return new ExchangeStrategiesDefaultWebClient(this);}// 其他配置選項,例如設置 ExchangeStrategies, ClientHttpRequestFactory 等
}
- baseUrl:定義客戶端的基礎 URL。
請求構建和發送
-
創建 WebClient 實例:使用 WebClient.Builder 創建并配置 WebClient 實例。
-
構建請求:使用 WebClient 的方法來添加請求頭、查詢參數、請求體等。
-
發起請求:調用 HTTP 方法對應的方法(如 getForObject、postForObject)來發起請求。
-
處理響應:響應以 Mono 或 Flux 的形式返回,可以進一步處理。
源碼實現步驟
- 配置和創建:通過 WebClient.Builder 配置基礎 URL 和其他選項,然后創建 WebClient 實例。
WebClient webClient = WebClient.builder().baseUrl("http://example.com").build();
構建請求:使用 WebClient 的方法鏈式構建請求。
Mono<Person> personMono = webClient.get().uri("/person/{id}", id).retrieve().bodyToMono(Person.class);
-
發起請求并獲取響應:調用 retrieve() 方法并指定響應體轉換的方式。
-
響應體轉換:使用 bodyToMono 或 bodyToFlux 等方法將響應體轉換為指定類型。
-
錯誤處理:使用 onErrorResume 或 onErrorMap 等操作符處理可能發生的錯誤。
-
訂閱和消費:訂閱響應體 Mono 或 Flux 并消費數據。
并發和異步處理
WebClient 支持并發和異步處理,允許以非阻塞的方式發起多個請求:
- 使用 Flux 可以處理多個響應。
- 可以使用 Scheduler 來控制并發級別。
小結一下
WebClient 是 Spring WebFlux 中一個強大且靈活的組件,用于構建非阻塞的響應式 HTTP 客戶端。它允許以聲明式的方式構建請求,并通過 Reactive Streams 規范支持異步數據處理。WebClient 的設計使得它非常適合在響應式應用程序中使用,可以充分利用現代異步編程的優勢,提高應用程序的性能和可伸縮性。
開發者可以輕松地使用 WebClient 與外部服務進行通信,獲取數據,并以響應式的方式處理這些數據。通過 WebClient,Spring WebFlux 應用程序可以無縫地集成到更大的響應式系統中。
12. Spring Data Reactive
Spring Data Reactive 是 Spring Data 項目的一部分,它提供了一組用于訪問響應式數據存儲的抽象。它允許以聲明式和響應式的方式進行數據訪問和操作,支持如 MongoDB、Redis、R2DBC(Reactive Relational Database Connectivity)等響應式數據庫。以下是對 Spring Data Reactive 組件的源碼實現邏輯和步驟的詳細分析:
Spring Data Reactive 核心概念
- Reactive Repository:擴展了 Reactive Streams 規范,提供了異步的 CRUD 操作。
- ReactiveCrudRepository:基礎接口,提供基本的 CRUD 操作。
- ReactiveMongoRepository、ReactiveRedisRepository 等:特定數據庫的實現。
Reactive Repository 接口定義
public interface ReactiveCrudRepository<T, ID> extends ReactiveRepository<T, ID> {Mono<T> save(T entity);Flux<T> findAll();Mono<T> findById(ID id);Mono<Void> deleteById(ID id);// 其他方法...
}
- save(T entity):保存實體。
- findAll():查找所有記錄。
- findById(ID id):通過 ID 查找記錄。
- deleteById(ID id):通過 ID 刪除記錄。
響應式數據訪問步驟
-
定義實體類:創建一個實體類,使用 JPA 注解或數據庫特定的注解標記字段。
-
定義倉庫接口:創建一個繼承自 ReactiveCrudRepository 或特定數據庫的 Repository 接口。
public interface MyEntityRepository extends ReactiveCrudRepository<MyEntity, Long> {// 可以添加自定義查詢方法}
-
配置數據源:配置響應式數據源和客戶端,例如配置 MongoDB 的 ReactiveMongoDatabase。
-
使用倉庫:在服務層注入并使用倉庫接口進行數據操作。
-
構建查詢:使用倉庫接口提供的方法或自定義查詢方法構建查詢。
-
異步處理:處理查詢結果,使用 Mono 或 Flux 的異步特性。
源碼實現邏輯
-
實體和倉庫定義:定義數據實體和倉庫接口。
-
Spring 應用上下文:Spring 應用上下文掃描倉庫接口并創建代理實現。
-
執行查詢:當調用倉庫接口的方法時,代理將方法調用轉換為數據庫操作。
-
結果封裝:查詢結果封裝在 Mono 或 Flux 中返回。
-
錯誤處理:處理可能發生的異常,將它們轉換為合適的響應。
-
響應式流控制:使用 Reactive Streams 規范控制數據流。
響應式數據庫操作示例
@Service
public class MyEntityService {private final MyEntityRepository repository;@Autowiredpublic MyEntityService(MyEntityRepository repository) {this.repository = repository;}public Mono<MyEntity> addMyEntity(MyEntity entity) {return repository.save(entity);}public Flux<MyEntity> getAllMyEntities() {return repository.findAll();}
}
小結一下
Spring Data Reactive 通過提供響應式倉庫接口,簡化了響應式數據訪問的實現。它利用了 Reactive Streams 規范,允許以非阻塞的方式進行數據庫操作,提高了應用程序的性能和可伸縮性。開發者可以輕松地定義倉庫接口,并使用 Spring 提供的 CRUD 方法或自定義查詢方法進行數據操作。
Spring Data Reactive 組件的設計允許它與現代響應式編程模型和框架(如 WebFlux)無縫集成,為構建響應式應用程序提供了強大的數據訪問能力。通過使用 Spring Data Reactive,開發者可以構建高效、彈性的應用程序,同時保持代碼的簡潔性和可維護性。
13. Spring Security Reactive
Spring Security Reactive 是 Spring Security 的響應式擴展,它為響應式應用程序提供了安全和認證支持。以下是對 Spring Security Reactive 組件的源碼實現邏輯和步驟的詳細分析:
Spring Security Reactive 核心概念
- ServerSecurityContextRepository:用于在請求中存儲和檢索 SecurityContext。
- ReactiveSecurityContextHolder:管理 SecurityContext 的持有者。
- ServerSecurityConfigurer:用于配置安全上下文。
- ServerHttpSecurity:定義了響應式 HTTP 安全策略。
- ReactiveAuthenticationManager 和 ReactiveUserDetailsService:用于用戶認證和用戶詳情服務。
ServerSecurityContextRepository 接口定義
public interface ServerSecurityContextRepository {Mono<Void> save(ServerSecurityContext context);Mono<ServerSecurityContext> load();void invalidate();
}
- save:保存 ServerSecurityContext。
- load:加載 ServerSecurityContext。
- invalidate:使 ServerSecurityContext 無效。
ServerHttpSecurity 配置
public class ServerHttpSecurity {public ServerHttpSecurity(ReactiveAuthenticationManager authentication) {// ...}public SecurityWebFilterChain build() {// ...}public ServerHttpSecurity authorizeExchange(Consumer<ServerAuthorizeExchangeSpec> configurer) {// ...}// 其他配置方法,例如 cors, csrf, formLogin, httpBasic 等
}
- authorizeExchange:配置授權策略。
- build:構建 SecurityWebFilterChain。
響應式認證和授權步驟
-
配置認證管理器:創建并配置 ReactiveAuthenticationManager。
-
配置用戶服務:創建并配置 ReactiveUserDetailsService。
-
構建 ServerHttpSecurity:使用 ServerHttpSecurity 構建安全策略。
-
配置安全上下文存儲:配置 ServerSecurityContextRepository。
-
注冊 WebFilter:將 SecurityWebFilterChain 注冊到 Web 過濾器鏈中。
-
處理認證和授權:在請求處理過程中,Spring Security Reactive 攔截請求并處理認證和授權。
源碼實現邏輯
-
初始化:在應用程序啟動時,Spring Security Reactive 初始化安全配置。
-
請求攔截:SecurityWebFilterChain 攔截請求并根據配置的安全策略進行處理。
-
認證:使用 ReactiveAuthenticationManager 進行用戶認證。
-
授權:根據 ServerHttpSecurity 配置的授權規則,使用 ReactiveAccessDecisionManager 進行訪問控制。
-
安全上下文:使用 ServerSecurityContextRepository 管理每個請求的安全上下文。
-
異常處理:處理安全相關的異常,如認證失敗或訪問拒絕。
-
響應:根據認證和授權的結果,構建響應并返回給客戶端。
小結一下
Spring Security Reactive 為響應式應用程序提供了全面的安全支持。它基于 Spring Security 的核心概念,并通過響應式編程模型提供了異步、非阻塞的安全處理能力。通過 ServerHttpSecurity 的配置,開發者可以靈活地定義認證和授權策略,以滿足不同應用程序的安全需求。
Spring Security Reactive 的設計允許它與 Spring WebFlux 無縫集成,為響應式 Web 應用程序提供強大的安全保障。通過使用 Spring Security Reactive,開發者可以構建安全、可靠且易于維護的響應式應用程序。
14. HttpHandler
HttpHandler 組件在 Spring WebFlux 中是一個用于處理 HTTP 請求的接口,它是響應式編程模型中最低層次的 HTTP 請求處理契約。HttpHandler 作為一個共同的接口,允許不同的運行時環境通過不同的實現來處理 HTTP 請求。以下是對 HttpHandler 組件的源碼實現邏輯和步驟的詳細分析:
HttpHandler 接口定義
HttpHandler 接口定義了一個 handle 方法,用于處理傳入的 HTTP 請求并返回一個響應:
public interface HttpHandler {Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response);
}
handle(ServerHttpRequest request, ServerHttpResponse response):處理給定的請求并構造響應。
核心職責
HttpHandler 的核心職責包括:
- 接收請求:接收 ServerHttpRequest 對象,該對象封裝了 HTTP 請求的詳細信息。
- 構造響應:根據請求信息構造 ServerHttpResponse 對象,設置狀態碼、響應頭等。
- 返回結果:返回一個 Mono
<Void>
?對象,表示異步的響應處理過程。
實現步驟
-
創建 HttpHandler 實例:實現 HttpHandler 接口或使用現有的實現。
-
處理請求:在 handle 方法中編寫邏輯以處理請求,例如路由、認證、業務處理等。
-
構造響應:根據請求的處理結果構造響應,設置狀態碼、響應頭和響應體。
-
返回 Mono
<Void>
:返回一個 Mono<Void>
,表示響應已經發送或將被發送。 -
錯誤處理:在 handle 方法中處理可能發生的異常,確保它們被適當地轉換為響應。
示例實現
以下是一個簡單的 HttpHandler 實現示例,它返回一個固定的響應:
public class SimpleHttpHandler implements HttpHandler {@Overridepublic Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {String body = "Hello, World!";response.getHeaders().add("Content-Type", "text/plain");return response.writeWith(Flux.just(DataBufferUtils.wrap(body)));}
}
小結一下
HttpHandler 組件是 Spring WebFlux 中用于處理 HTTP 請求的基礎接口。它提供了一個簡單而靈活的方式來處理 HTTP 請求和構造響應。通過實現 HttpHandler 接口,開發者可以控制整個請求處理流程,包括請求解析、業務邏輯處理和響應構建。
HttpHandler 的實現可以與其他 Spring WebFlux 組件(如 DispatcherHandler、HandlerMapping、HandlerAdapter 等)結合使用,以構建一個完整的響應式 Web 應用程序。這種低層次的接口為需要高度定制的 Web 應用程序提供了強大的靈活性。
15. ContextPathCompositeHandler
ContextPathCompositeHandler 是 Spring WebFlux 中的一個組件,它允許在同一服務器上將多個應用程序映射到不同的上下文路徑(context paths)。這類似于在傳統的 Servlet 容器中為每個 Web 應用程序配置不同的 URL 路徑。
以下是對 ContextPathCompositeHandler 組件的源碼實現邏輯和步驟的詳細分析:
ContextPathCompositeHandler 接口定義
ContextPathCompositeHandler 實際上不是一個接口,而是 HandlerMapping 接口的一個實現,它組合了多個 Handler 對象,每個對象都關聯一個上下文路徑。
主要屬性
- contextPaths:存儲上下文路徑和對應的 Handler 映射。
- pattern:用于匹配請求路徑的正則表達式。
上下文路徑映射
ContextPathCompositeHandler 維護了一個映射,將每個上下文路徑映射到一個 Handler:
private final Map<String, HttpHandler> contextPaths = new ConcurrentHashMap<>();
添加應用程序
應用程序可以在初始化時通過 ContextPathCompositeHandler 的 addHandler 方法添加到映射中:
public void addHandler(String contextPath, HttpHandler handler) {this.contextPaths.put(contextPath, handler);// 更新正則表達式模式以匹配所有注冊的上下文路徑updatePattern();
}
處理請求
ContextPathCompositeHandler 通過 getHandler 方法來確定請求應該由哪個 Handler 處理:
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {String path = extractContextPath(exchange);return Mono.justOrEmpty(contextPaths.get(path)).map(HandlerAdapter::new).defaultIfEmpty(Mono.defer(() -> createNotFoundError(exchange)));
}
- extractContextPath:提取請求的上下文路徑。
- getHandler:根據上下文路徑從映射中獲取對應的 Handler。
正則表達式模式
ContextPathCompositeHandler 使用正則表達式來匹配請求路徑:
private void updatePattern() {// 構建匹配所有注冊上下文路徑的正則表達式String regex = contextPaths.keySet().stream().map(this::toRegex).collect(Collectors.joining("|", "^(", ")$"));this.compiledPattern = Pattern.compile(regex);
}
錯誤處理
如果沒有找到匹配的上下文路徑,ContextPathCompositeHandler 會創建一個表示 "Not Found" 的錯誤處理器:
private Mono<HandlerAdapter> createNotFoundError(ServerWebExchange exchange) {return Mono.just(new HandlerAdapter() {@Overridepublic boolean supports(Object handler) {return true;}@Overridepublic Mono<Void> handle(ServerWebExchange exchange, Object handler) {return ServerResponse.notFound().build().writeTo(exchange);}});
}
小結一下
ContextPathCompositeHandler 組件是 Spring WebFlux 中用于將多個應用程序映射到不同上下文路徑的 HandlerMapping 實現。它通過維護一個上下文路徑到 HttpHandler 的映射,允許每個應用程序處理其自己的請求路徑。通過正則表達式匹配請求路徑,并使用 HandlerAdapter 來適配和調用相應的處理器。
這種設計模式使得在單個服務器實例中部署和管理多個 WebFlux 應用程序變得簡單和高效,每個應用程序都可以有自己的上下文路徑,而 ContextPathCompositeHandler 負責將請求路由到正確的應用程序處理器。