Spring Boot 2 快速教程:WebFlux處理流程(五)

WebFlux請求處理流程

下面是spring mvc的請求處理流程

img

img

具體步驟:

  • 第一步:發起請求到前端控制器(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請求處理流程

img

我們可以對比SpringMVC的請求流程圖對比來看

img

我們可以看到,處理流程基本一樣,有以下主要的點不同

  • 處理核心
    • WebFlux--DispatcherHandler
    • SpringMvc--DispatcherServlet
  • 返回值處理器
    • WebFlux--HandlerResultHandler
    • SpringMvc--HandlerMethodReturnValueHandler
  • 內容協商配置器
    • WebFlux--RequestedContentTypeResolverBuilder
    • SpringMvc--ContentNegotiationConfigurer

還有很多就不一一例舉了,想知道核心組件對比結果的同學,可以看下圖。注意很多圖上的組件名稱相同,但是包的位置是不同的,所以大家要注意區分,不要弄混了。

Web MVC VS. WebFlux 核心組件對比

img

WebFlux 都有哪些核心組件

Spring WebFlux 包含多個核心組件,它們共同構成了完整的響應式 Web 應用框架。下面是一些主要的核心組件:

  1. DispatcherHandler:這是 WebFlux 的中央調度器,類似于 Spring MVC 中的 DispatcherServlet。它負責發現和調度 HTTP 請求處理器(handlers),并處理請求映射、調用和結果處理。

  2. HandlerMapping:這個接口用于將請求映射到對應的處理器(handler)。它在應用程序上下文中被檢測到,并用于確定請求應該由哪個處理器處理。

  3. HandlerAdapter:這個接口幫助 DispatcherHandler 調用任何類型的處理器,而不需要關心具體的調用方式。它為不同的處理器提供了調用策略。

  4. HandlerResultHandler:這個接口處理處理器調用后的結果,并生成最終的響應。它負責將處理器的結果轉換為客戶端可以接收的格式。

  5. WebFilter:WebFilter 接口定義了一組過濾器,這些過濾器可以對請求和響應進行預處理和后處理。

  6. ServerWebExchange:這個類封裝了 HTTP 請求和響應的所有信息,例如請求頭、請求體、URI、參數等。

  7. ServerHttpRequest 和 ServerHttpResponse:這兩個類分別代表服務器接收的 HTTP 請求和發送的 HTTP 響應。

  8. WebSession:用于管理特定客戶端的會話信息。

  9. Reactive Streams:WebFlux 基于 Reactive Streams 規范,使用非阻塞背壓機制來處理數據流。

  10. Reactor 庫:作為 Spring 5 的反應式編程基礎,Reactor 提供了非阻塞的編程模型和工具,包括 Flux 和 Mono 等反應式類型。

  11. WebClient:這是 Spring 5 中引入的非阻塞、支持響應式流的 HTTP 客戶端,用于與其它服務進行通信。

  12. Spring Data Reactive:提供對響應式數據訪問的支持,例如 Reactive Repositories。

  13. Spring Security Reactive:提供對響應式安全訪問控制的支持。

  14. HttpHandler:定義了最低級別的反應式 HTTP 請求處理合同,作為不同運行時之間的共同基礎。

  15. 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 規范定義了以下幾個核心接口:

  1. Publisher<T>:發布者,表示可以產生數據的源頭。
  2. Subscriber<T>:訂閱者,表示接收并處理數據的消費者。
  3. Subscription:訂閱關系,用于管理數據的請求和發送。
  4. 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 負責將請求路由到正確的應用程序處理器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/894594.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/894594.shtml
英文地址,請注明出處:http://en.pswp.cn/news/894594.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小程序設計和開發:如何研究同類型小程序的優點和不足。

一、確定研究目標和范圍 明確研究目的 在開始研究同類型小程序之前&#xff0c;首先需要明確研究的目的。是為了改進自己的小程序設計和開發&#xff0c;還是為了了解市場趨勢和用戶需求&#xff1f;不同的研究目的會影響研究的方法和重點。例如&#xff0c;如果研究目的是為了…

使用 Numpy 自定義數據集,使用pytorch框架實現邏輯回歸并保存模型,然后保存模型后再加載模型進行預測,對預測結果計算精確度和召回率及F1分數

1. 導入必要的庫 首先&#xff0c;導入我們需要的庫&#xff1a;Numpy、Pytorch 和相關工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定義數據集 …

Unity-編譯構建Android的問題記錄

文章目錄 報錯&#xff1a;AAPT2 aapt2-4.1.2-6503028-osx Daemon #0 Failed to shutdown within timeout報錯信息解讀&#xff1a;原因分析最終處理方法 報錯&#xff1a;AAPT2 aapt2-4.1.2-6503028-osx Daemon #0 Failed to shutdown within timeout 報錯信息解讀&#xff1…

【axios二次封裝】

axios二次封裝 安裝封裝使用 安裝 pnpm add axios封裝 // 進行axios二次封裝&#xff1a;使用請求與響應攔截器 import axios from axios import { ElMessage } from element-plus//創建axios實例 const request axios.create({baseURL: import.meta.env.VITE_APP_BASE_API,…

SQL進階實戰技巧:如何構建用戶行為轉移概率矩陣,深入洞察會話內活動流轉?

目錄 1 場景描述 1.1 用戶行為轉移概率矩陣概念 1.2 用戶行為轉移概率矩陣構建方法 (1) 數據收集

Vue3.0實戰:大數據平臺可視化(附完整項目源碼)

文章目錄 創建vue3.0項目項目初始化項目分辨率響應式設置項目頂部信息條創建頁面主體創建全局引入echarts和axios后臺接口創建express銷售總量圖實現完整項目下載項目任何問題都可在評論區,或者直接私信即可。 創建vue3.0項目 創建項目: vue create vueecharts選擇第三項:…

Java自定義IO密集型和CPU密集型線程池

文章目錄 前言線程池各類場景描述常見場景案例設計思路公共類自定義工廠類-MyThreadFactory自定義拒絕策略-RejectedExecutionHandlerFactory自定義阻塞隊列-TaskQueue&#xff08;實現 核心線程->最大線程數->隊列&#xff09; 場景1&#xff1a;CPU密集型場景思路&…

【VM】VirtualBox安裝ubuntu22.04虛擬機

閱讀本文之前&#xff0c;請先根據 安裝virtualbox 教程安裝virtulbox虛擬機軟件。 1.下載Ubuntu系統鏡像 打開阿里云的鏡像站點&#xff1a;https://developer.aliyun.com/mirror/ 找到如圖所示位置&#xff0c;選擇Ubuntu 22.04.3(destop-amd64)系統 Ubuntu 22.04.3(desto…

Pandas基礎08(分箱操作/時間序列/畫圖)

3.8.1 Pandas分箱操作 數據分箱&#xff08;Binning&#xff09; 是一種數據預處理方法&#xff0c;用于將連續型變量的數值范圍分割成若干個區間或“箱”&#xff08;bins&#xff09;&#xff0c;將數據按照這些區間進行分類&#xff0c;從而轉換為離散型變量。這種方法常用…

C#,shell32 + 調用控制面板項(.Cpl)實現“新建快捷方式對話框”(全網首發)

Made By 于子軒&#xff0c;2025.2.2 不管是使用System.IO命名空間下的File類來創建快捷方式文件&#xff0c;或是使用Windows Script Host對象創建快捷方式&#xff0c;亦或是使用Shell32對象創建快捷方式&#xff0c;都對用戶很不友好&#xff0c;今天小編為大家帶來一種全新…

國產編輯器EverEdit - 輸出窗口

1 輸出窗口 1.1 應用場景 輸出窗口可以顯示用戶執行某些操作的結果&#xff0c;主要包括&#xff1a; 查找類&#xff1a;查找全部&#xff0c;篩選等待操作&#xff0c;可以把查找結果打印到輸出窗口中&#xff1b; 程序類&#xff1a;在執行外部程序時(如&#xff1a;命令窗…

Vue-data數據

目錄 一、Vue中的data數據是什么&#xff1f;二、data支持的數據類型有哪些&#xff1f; 一、Vue中的data數據是什么&#xff1f; Vue中用到的數據定義在data中。 二、data支持的數據類型有哪些&#xff1f; data中可以寫復雜類型的數據&#xff0c;渲染復雜類型數據時只要遵…

02.03 遞歸運算

使用遞歸求出 1 1/3 -1/5 1/7 - 1/9 ... 1/n的值。 1>程序代碼 #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #inc…

數據分析系列--⑥RapidMiner構建決策樹(泰坦尼克號案例含數據)

一、資源下載 二、數據處理 1.導入數據 2.數據預處理 三、構建模型 1.構建決策樹 2.劃分訓練集和測試集 3.應用模型 4.結果分析 一、資源下載 點擊下載數據集 二、數據處理 1.導入數據 2.數據預處理 三、構建模型 1.構建決策樹 雖然決策樹已經構建,但對于大多數初學者或…

高階開發基礎——快速入門C++并發編程6——大作業:實現一個超級迷你的線程池

目錄 實現一個無返回的線程池 完全代碼實現 Reference 實現一個無返回的線程池 實現一個簡單的線程池非常簡單&#xff0c;我們首先聊一聊線程池的定義&#xff1a; 線程池&#xff08;Thread Pool&#xff09; 是一種并發編程的設計模式&#xff0c;用于管理和復用多個線程…

pytorch實現主成分分析 (PCA):用于數據降維和特征提取

人工智能例子匯總&#xff1a;AI常見的算法和例子-CSDN博客 使用 PyTorch 實現主成分分析&#xff08;PCA&#xff09;可以通過以下步驟進行&#xff1a; 標準化數據&#xff1a;首先&#xff0c;需要對數據進行標準化處理&#xff0c;確保每個特征的均值為 0&#xff0c;方差…

100 ,【8】 buuctf web [藍帽杯 2021]One Pointer PHP(別看)

進入靶場 沒提示&#xff0c;去看源代碼。 user.php <?php // 定義一個名為 User 的類&#xff0c;該類可用于表示用戶相關信息或執行與用戶有關的操作 class User{// 聲明一個公共屬性 $count&#xff0c;可在類的內部和外部直接訪問// 這個屬性可能用于記錄與用戶相關…

巧妙利用數據結構優化部門查詢

目錄 一、出現的問題 部門樹接口超時 二、問題分析 源代碼分析 三、解決方案 具體實現思路 四、優化的效果 一、出現的問題 部門樹接口超時 無論是在A項目還是在B項目中&#xff0c;都存在類似的頁面&#xff0c;其實就是一個部門列表或者叫組織列表。 從頁面的展示形式…

QT簡單實現驗證碼(字符)

0&#xff09; 運行結果 1&#xff09; 生成隨機字符串 Qt主要通過QRandomGenerator類來生成隨機數。在此之前的版本中&#xff0c;qrand()函數也常被使用&#xff0c;但從Qt 5.10起&#xff0c;推薦使用更現代化的QRandomGenerator類。 在頭文件添加void generateRandomNumb…

JavaFX - 3D 形狀

在前面的章節中&#xff0c;我們已經了解了如何在 JavaFX 應用程序中的 XY 平面上繪制 2D 形狀。除了這些 2D 形狀之外&#xff0c;我們還可以使用 JavaFX 繪制其他幾個 3D 形狀。 通常&#xff0c;3D 形狀是可以在 XYZ 平面上繪制的幾何圖形。它們由兩個或多個維度定義&#…