DispatcherHandler

Spring WebFlux 與 Spring MVC 類似,是圍繞前端控制器模式設計的,其中中央 WebHandler,即 DispatcherHandler,為請求處理提供共用演算法,而實際工作由可組態的委派元件執行。此模型非常彈性,並支援多樣的工作流程。

DispatcherHandler 從 Spring 組態中探索其所需的委派元件。它也被設計為 Spring Bean 本身,並實作 ApplicationContextAware 以存取其執行的 Context。如果 DispatcherHandlerwebHandler 的 Bean 名稱宣告,則它會反過來被 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 組態 是最佳起點。它宣告了所需的 Bean,並提供更高等級的組態回呼 API 來自訂它。

Spring Boot 依賴 WebFlux 組態來組態 Spring WebFlux,並提供許多額外的便利選項。

處理

DispatcherHandler 依循以下步驟處理請求

  • 每個 HandlerMapping 都會被要求尋找符合的處理器,並使用第一個符合的處理器。

  • 如果找到處理器,則會透過適當的 HandlerAdapter 執行,後者會將執行的傳回值公開為 HandlerResult

  • HandlerResult 會被提供給適當的 HandlerResultHandler,以透過直接寫入回應或使用視圖呈現來完成處理。

結果處理

透過 HandlerAdapter 呼叫處理器的傳回值會被包裝為 HandlerResult,連同一些額外的 Context,並傳遞給第一個聲稱支援它的 HandlerResultHandler。下表顯示可用的 HandlerResultHandler 實作,所有這些實作都在 WebFlux 組態 中宣告

結果處理器類型 傳回值 預設順序

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 包含來自處理器的傳回值,以及包含在請求處理期間新增的屬性的模型。傳回值會以下列方式之一處理

  • StringCharSequence:要透過已組態的 ViewResolver 實作列表解析為 View 的邏輯視圖名稱。

  • void:根據請求路徑(減去前導和尾隨斜線)選擇預設視圖名稱,並將其解析為 View。當未提供視圖名稱(例如,傳回模型屬性)或非同步傳回值(例如,Mono 完成時為空)時,也會發生相同的情況。

  • Rendering:用於視圖解析場景的 API。在您的 IDE 中使用程式碼完成功能探索選項。

  • ModelMap:要新增至請求模型的額外模型屬性。

  • 任何其他:任何其他傳回值(簡單類型除外,由 BeanUtils#isSimpleProperty 判斷)都會被視為要新增至模型的模型屬性。屬性名稱是使用 慣例 從類別名稱衍生而來,除非存在處理器方法 @ModelAttribute 註解。

模型可以包含非同步、反應式類型(例如,來自 Reactor 或 RxJava)。在呈現之前,AbstractView 會將此類模型屬性解析為具體值並更新模型。單一值反應式類型會解析為單一值或無值(如果為空),而多值反應式類型(例如,Flux<T>)會被收集並解析為 List<T>

組態視圖解析就像將 ViewResolutionResultHandler Bean 新增至您的 Spring 組態一樣簡單。WebFlux 組態 為視圖解析提供專用的組態 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 支援的媒體類型進行比較。使用第一個支援請求媒體類型的 View

為了支援諸如 JSON 和 XML 之類的媒體類型,Spring WebFlux 提供了 HttpMessageWriterView,這是一個特殊的 View,它透過 HttpMessageWriter 呈現。通常,您會透過 WebFlux 組態 將這些組態為預設視圖。如果預設視圖符合請求的媒體類型,則始終會選取並使用它們。