DispatcherHandler

Spring WebFlux 與 Spring MVC 類似,圍繞前端控制器(front controller)模式設計,其中核心的 WebHandler,即 DispatcherHandler,提供了一個共享的請求處理演算法,而實際工作則由可配置的委託元件執行。這種模型靈活,支援多種工作流。

DispatcherHandler 從 Spring 配置中發現其所需的委託元件。它也被設計為一個 Spring bean,並實現了 ApplicationContextAware 介面,以便訪問其執行所在的上下文。如果 DispatcherHandler 的 bean 名稱宣告為 webHandler,那麼它將由 WebHttpHandlerBuilder 發現,後者會組裝一個請求處理鏈,如 WebHandler API 中所述。

WebFlux 應用中的 Spring 配置通常包含

將配置提供給 WebHttpHandlerBuilder 以構建處理鏈,如下例所示

  • Java

  • Kotlin

ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
val context: ApplicationContext = ...
val handler = WebHttpHandlerBuilder.applicationContext(context).build()

生成的 HttpHandler 已準備好與 伺服器介面卡 一起使用。

特殊 Bean 型別

DispatcherHandler 將請求處理和相應響應的渲染委託給特殊 bean。這裡的“特殊 bean”指的是實現了 WebFlux 框架契約的 Spring 管理的 Object 例項。它們通常帶有內建的契約,但您可以自定義它們的屬性、擴充套件或替換它們。

下表列出了 DispatcherHandler 檢測到的特殊 bean。請注意,還有一些在更低級別檢測到的其他 bean(請參閱 Web Handler API 中的 特殊 bean 型別)。

Bean 型別 解釋

HandlerMapping

將請求對映到處理器。對映基於某些標準,其詳細資訊因 HandlerMapping 實現而異——註解控制器、簡單的 URL 模式對映等。

主要的 HandlerMapping 實現包括用於 `@RequestMapping` 註解方法的 RequestMappingHandlerMapping,用於函式式端點路由的 RouterFunctionMapping,以及用於顯式註冊 URI 路徑模式和 WebHandler 例項的 SimpleUrlHandlerMapping

HandlerAdapter

幫助 DispatcherHandler 呼叫對映到請求的處理器,而不管處理器實際如何呼叫。例如,呼叫註解控制器需要解析註解。HandlerAdapter 的主要目的是遮蔽 DispatcherHandler 免受這些細節的影響。

HandlerResultHandler

處理處理器呼叫結果並完成響應。請參閱 結果處理

WebFlux 配置

應用可以宣告處理請求所需的基礎設施 bean(列在 Web Handler APIDispatcherHandler 下)。然而,在大多數情況下,WebFlux Config 是最好的起點。它聲明瞭所需的 bean,並提供了一個更高級別的配置回撥 API 來定製它。

Spring Boot 依賴 WebFlux 配置來配置 Spring WebFlux,並提供了許多額外的便捷選項。

處理流程

DispatcherHandler 按以下方式處理請求

  • 每個 HandlerMapping 被要求查詢匹配的處理器,並使用第一個匹配項。

  • 如果找到處理器,它將透過適當的 HandlerAdapter 執行,HandlerAdapter 將執行的返回值暴露為 HandlerResult

  • HandlerResult 被交給適當的 HandlerResultHandler,透過直接寫入響應或使用檢視渲染來完成處理。

結果處理

透過 HandlerAdapter 呼叫處理器返回的值被包裝成一個 HandlerResult,以及一些額外的上下文,並傳遞給第一個聲稱支援它的 HandlerResultHandler。下表顯示了可用的 HandlerResultHandler 實現,所有這些都在 WebFlux Config 中宣告。

結果處理器型別 返回值 預設順序

ResponseEntityResultHandler

ResponseEntity,通常來自 `@Controller` 例項。

0

ServerResponseResultHandler

ServerResponse,通常來自函式式端點。

0

ResponseBodyResultHandler

處理來自 `@ResponseBody` 方法或 `@RestController` 類的返回值。

100

ViewResolutionResultHandler

CharSequenceViewModelMapRendering 或任何其他 Object 被視為模型屬性。

另請參閱 檢視解析

Integer.MAX_VALUE

異常

HandlerAdapter 實現可以內部處理呼叫請求處理器(例如控制器方法)時發生的異常。然而,如果請求處理器返回非同步值,異常可能會被延遲處理。

一個 HandlerAdapter 可以將其異常處理機制作為設定在其返回的 HandlerResult 上的 DispatchExceptionHandler 暴露出來。設定後,DispatcherHandler 也會將其應用於結果的處理。

一個 HandlerAdapter 也可以選擇實現 DispatchExceptionHandler。在這種情況下,DispatcherHandler 會將其應用於在處理器對映之前發生的異常,例如在處理器對映期間,或更早的時候,例如在 WebFilter 中。

另請參閱“註解控制器”章節中的 異常 或 WebHandler API 章節中的 異常

檢視解析

檢視解析使得可以使用 HTML 模板和模型向瀏覽器渲染,而無需繫結到特定的檢視技術。在 Spring WebFlux 中,檢視解析透過一個專門的 HandlerResultHandler 支援,該處理器使用 ViewResolver 例項將字串(表示邏輯檢視名)對映到 View 例項。然後使用該 View 來渲染響應。

Web 應用需要使用 檢視渲染庫 來支援此用例。

處理

傳遞給 ViewResolutionResultHandlerHandlerResult 包含處理器的返回值以及在請求處理期間添加了屬性的模型。返回值按以下方式之一進行處理

  • String, CharSequence: 一個邏輯檢視名,將透過配置的 ViewResolver 實現列表解析為 View

  • void: 基於請求路徑選擇一個預設檢視名(去除前導和尾部斜槓),並將其解析為 View。當未提供檢視名(例如,返回了模型屬性)或非同步返回值(例如,Mono 完成時為空)時,也會發生同樣的情況。

  • Rendering: 用於檢視解析場景的 API。請在您的 IDE 中透過程式碼補全探索選項。

  • Model, Map: 要新增到請求模型的額外模型屬性。

  • 任何其他型別:任何其他返回值(簡單型別除外,由 BeanUtils#isSimpleProperty 確定)被視為要新增到模型的模型屬性。屬性名使用 約定 從類名派生,除非存在處理方法上的 `@ModelAttribute` 註解。

模型可以包含非同步的、響應式型別(例如,來自 Reactor 或 RxJava)。在渲染之前,AbstractView 將這些模型屬性解析為具體值並更新模型。單值響應式型別被解析為單個值或無值(如果為空),而多值響應式型別(例如,Flux<T>)則被收集並解析為 List<T>

配置檢視解析就像向您的 Spring 配置中新增一個 ViewResolutionResultHandler bean 一樣簡單。WebFlux Config 為檢視解析提供了一個專門的配置 API。

有關與 Spring WebFlux 整合的檢視技術的更多資訊,請參閱 檢視技術

重定向

檢視名中的特殊字首 redirect: 允許您執行重定向。UrlBasedViewResolver(及其子類)將其識別為需要重定向的指令。檢視名的其餘部分是重定向 URL。

最終效果與控制器返回 RedirectViewRendering.redirectTo(\"abc\").build() 相同,但現在控制器本身可以使用邏輯檢視名進行操作。例如,redirect:/some/resource 檢視名相對於當前應用,而 redirect:https://example.com/arbitrary/path 檢視名則重定向到絕對 URL。

與 Servlet 棧不同,Spring WebFlux 不支援“FORWARD”分派,因此結果不支援 forward: 字首。

內容協商

ViewResolutionResultHandler 支援內容協商。它將請求的媒體型別與每個選定 View 支援的媒體型別進行比較。使用第一個支援請求媒體型別(s) 的 View

為了支援 JSON 和 XML 等媒體型別,Spring WebFlux 提供了 HttpMessageWriterView,這是一個特殊的 View,它透過 HttpMessageWriter 進行渲染。通常,您會透過 WebFlux 配置 將這些配置為預設檢視。如果預設檢視與請求的媒體型別匹配,則總是會被選中並使用。