Stories

Detail Return Return

深度長文解析SpringWebFlux響應式框架15個核心組件源碼 - Stories Detail

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哥每天更新的原創技術內容,讓我們一起成長。

user avatar _58d8892485f34 Avatar ddup365 Avatar nut Avatar user_4jsjtpci Avatar hole Avatar yinshule Avatar shawn_5dd516205b8bd Avatar _5bf4c360ce464 Avatar qiangjiandebinggan Avatar
Favorites 9 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.