深度長文解析SpringWebFlux響應式框架15個核心元件原始碼

威哥爱编程發表於2024-07-04

Spring WebFlux 介紹

Spring WebFlux 是 Spring Framework 5.0 版本引入的一個響應式 Web 框架,它與 Spring MVC 並存,提供了一種全新的程式設計正規化,支援非同步非阻塞的 Web 應用開發。WebFlux 完全基於響應式程式設計模型,支援 Reactive Streams 規範,可以在諸如 Netty、Undertow 以及 Servlet 3.1+ 容器上執行。

WebFlux 的核心控制器是 DispatcherHandler,它類似於 Spring MVC 中的 DispatcherServlet,負責將請求分發給相應的處理器。DispatcherHandler 透過查詢 Spring 配置中的 HandlerMapping、HandlerAdapter 和 HandlerResultHandler 來處理請求。

在 WebFlux 中,Flux 和 Mono 是 Reactor 庫中的兩個基本概念,分別用於表示包含 0 到 N 個元素和 0 或 1 個元素的非同步序列。Flux 可以用於表示一個包含多個響應式元素的流,而 Mono 用於表示單個元素的響應式流。

Spring WebFlux 支援多種程式設計模式,包括基於註解的控制器和函式式端點。開發者可以使用 @RestController 註解來建立響應式控制器,並使用 @GetMapping、@PostMapping 等註解來處理 HTTP 請求。同時,WebFlux 也支援使用 WebClient 作為非阻塞的 HTTP 客戶端來與其它服務進行通訊。

WebFlux 的併發模型與傳統的 Spring MVC 有顯著不同。它利用了少量的執行緒來處理大量的併發請求,這得益於其非阻塞的特性。當執行在 Netty 伺服器上時,WebFlux 使用事件迴圈執行緒來處理請求,避免了傳統 Servlet 容器中每個請求都需要一個執行緒的模型。

Spring WebFlux 的適用場景主要是 IO 密集型的應用,例如微服務閘道器,它可以顯著提升對下游服務轉發的吞吐量
。然而,如果現有的 Spring MVC 應用能夠滿足效能需求,並且專案中使用了許多基於 Servlet 執行緒模型的庫,那麼可能沒有必要遷移到 WebFlux。

原始碼層面,Spring WebFlux 的請求處理流程涉及到多個元件,包括 Netty 伺服器的初始化、請求的接收、DispatcherHandler 的請求分發,以及最終的請求處理和響應。在 Netty 伺服器中,請求處理涉及到 ChannelHandler,ConnectionObserver,以及 HttpHandler 等多個元件。這些元件協同工作,實現了 WebFlux 的非阻塞和響應式特性。

Spring 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) {
    // 檢查是否初始化了 handlerMappings
    if (this.handlerMappings == null) {
        return createNotFoundError();
    }
    // 使用 handlerMappings 來查詢 handler
    return 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 方法呼叫處理器,並處理返回值。

    @Override
    public 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 物件,並生成響應。
    @Override
    public 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 {
    @Bean
    public 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;

    @Autowired
    public 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 {

    @Override
    public 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() {
        @Override
        public boolean supports(Object handler) {
            return true;
        }

        @Override
        public Mono<Void> handle(ServerWebExchange exchange, Object handler) {
            return ServerResponse.notFound().build().writeTo(exchange);
        }
    });
}

小結一下

ContextPathCompositeHandler 元件是 Spring WebFlux 中用於將多個應用程式對映到不同上下文路徑的 HandlerMapping 實現。它透過維護一個上下文路徑到 HttpHandler 的對映,允許每個應用程式處理其自己的請求路徑。透過正規表示式匹配請求路徑,並使用 HandlerAdapter 來適配和呼叫相應的處理器。

這種設計模式使得在單個伺服器例項中部署和管理多個 WebFlux 應用程式變得簡單和高效,每個應用程式都可以有自己的上下文路徑,而 ContextPathCompositeHandler 負責將請求路由到正確的應用程式處理器。

最後

以上是Spring WebFlux 框架核心元件的全部介紹了,希望可以幫助你全面深入的理解 WebFlux的原理,關注【威哥愛程式設計】,主頁裡可檢視V哥每天更新的原創技術內容,讓我們一起成長。

相關文章