[TOC]
## `DispatcherHandler`介紹
與`Spring MVC`類似,`Spring WebFlux`是圍繞前端控制器模式設計的,其中一個中心`WebHandler` `DispatcherHandler`為請求處理提供了一個共享算法,而實際的工作是由可配置的委托組件執行的。這個模型是靈活的,并支持不同的工作流。
`DispatcherHandler`從`Spring`配置中發現它需要的委托組件。它本身也被設計成一個`Spring Bean`,并實現了`ApplicationContextAware`來訪問它運行的上下文。如果`DispatcherHandler`用一個`Bean`名`webHandler`聲明,那么它會被`WebHttpHandlerBuilder`發現,后者將請求處理鏈放在一起。
`WebFlux`應用中的`Spring`配置通常包括:
* `DispatcherHandler Bean` 名稱為`webHandler`
* `WebFilter`和`WebExceptionHandler` `Bean`
* `DispatcherHandler`特殊`Bean`
* 其它
提供配置給`WebHttpHandlerBuilder`來構建處理鏈,如下面的示例所示
~~~
ApplicationContext context = ...
WebHttpHandlerBuilder.applicationContext(context).filter(...).webHandler(...).exceptionHandler(...)
.sessionManager(...).codecConfigurer(...).localeContextResolver(...).forwardedHeaderTransformer(...);
~~~
## `DispatcherHandler`特殊的`Bean`類型
`DispatcherHandler`委托給特殊的`bean`來處理請求和呈現響應。所謂“`特殊bean`”,我們指的是實現`WebFlux`框架契約的`Spring`管理對象實例。它們通常帶有內置契約,可以自定義、擴展或替換它們。
| Bean | 說明 |
| --- | --- |
| `HandlerMapping` | 將請求映射到處理程序。映射基于一些標準,這些標準的細節因`HandlerMapping`實現而不同——帶注解的`Controller`、簡單的`URL`模式映射等等。主要的`HandlerMapping`實現是`@RequestMapping`帶注解方法的`RequestMappingHandlerMapping` ,`RouterFunctionMapping`用于功能性端點路由,`SimpleUrlHandlerMapping`用于顯式注冊`URI`路徑模式和`WebHandler`實例。|
|`HandlerAdapter`|幫助`DispatcherHandler`調用映射到請求的處理程序,而不管該處理程序實際是如何調用的。例如,調用帶注解的控制器需要解析注解。`HandlerAdapter`的主要目的是保護`DispatcherHandler`不受此類細節的影響。|
|`HandlerResultHandler`|處理`處理程序`調用的結果并完成響應|
## 請求處理流程
DispatcherHandler按如下方式處理請求:
1.要求每個HandlerMapping查找匹配的處理程序,并使用第一個匹配。
2.如果找到了處理程序,則通過適當的HandlerAdapter運行它,它將執行的返回值轉換成HandlerResult。
3.HandlerResult被賦予適當的HandlerResultHandler,通過直接寫入響應或使用視圖來呈現來完成處理。
## `HandlerMapping`
接口,由定義請求和處理程序對象之間映射的對象實現。默認實現類圖如下:

| Bean | 說明 |
| --- | --- |
|SimpleUrlHandlerMapping|從`URL`映射到請求處理程序`Bean`。支持映射到Bean實例和映射到Bean名稱;后者對于非單例處理程序是必需的。例如:/welcome.html=ticketController|
| RequestMappingHandlerMapping | RequestMappingInfoHandlerMapping的擴展,從類級和方法級的@RequestMapping注解中創建RequestMappingInfo實例。 |
|RouterFunctionMapping|支持RouterFunctions的HandlerMapping實現。如果在構造時沒有提供RouterFunction,這個映射將檢測應用程序上下文中所有的路由器函數,并按順序查詢它們。|
## HandlerAdapter
它將`DispatcherHandler`從調用處理程序的細節中解耦,并使支持任何處理程序類型成為可能。

| Bean | 說明 |
| --- | --- |
| SimpleHandlerAdapter | 允許使用普通WebHandler契約的HandlerAdapter |
|HandlerFunctionAdapter|支持HandlerFunctions的HandlerAdapter實現|
|RequestMappingHandlerAdapter|支持@RequestMapping處理程序方法的調用|
|WebSocketHandlerAdapter|允許WebSocketHandler類型的處理程序,這些處理程序通過SimpleUrlHandlerMapping映射到URL模式|
## HandlerResultHandler

處理程序調用的返回值通過`HandlerAdapter`被包裝為`HandlerResult`和一些附加上下文,并傳遞給聲稱支持它的第一個`HandlerResultHandler`。下表顯示了可用的`HandlerResultHandler`實現,所有這些實現都在`WebFlux`配置中聲明:
| | | |
| --- | --- |--- |
| ResponseEntityResultHandler | 處理HttpEntity和ResponseEntity返回值。 | 0 |
| ServerResponseResultHandler | 支持ServerResponses的HandlerResultHandler實現,通常用于功能端點 | 0 |
| ResponseBodyResultHandler | 處理@ResponseBody方法或@RestController類的返回值。 | 100|
| ViewResolutionResultHandler | CharSequence、View、Model、Map、Rendering或任何其他對象都被視為模型屬性。 | Integer.MAX\_VALUE |
</br>
## 視圖解析
視圖解析器允許使用`HTML`模板和模型向瀏覽器呈現,而無需將你綁定到特定的視圖技術。在`Spring WebFlux`中,視圖解析是通過一個專用的`HandlerResultHandler`來支持的,該`HandlerResultHandler`使用`ViewResolver`實例來映射一個`String`(代表一個邏輯視圖名)到一個`View`實例,然后使用視圖來呈現響應。
`ViewResolutionResultHandler`封裝了支持以下返回類型的視圖解析算法:
* Void 或空值 -- 默認視圖名
* String -- 視圖名,除了@ModelAttribute注解
* View -- 要渲染的視圖
* Model -- 屬性添加到模型
* Map -- 屬性添加到模型
* Rendering -- 用例驅動的API用于視圖解析
* @ModelAttribute -- 模型的屬性
* 復雜的值 -- 模型的屬性
### 處理
傳遞給`ViewResolutionResultHandler`的`HandlerResult`包含來自處理程序的返回值和包含在請求處理期間添加的屬性的模型。返回值的處理方式如下:
* `String`,`CharSequence`: 通過配置的ViewResolver實現列表解析為view的邏輯視圖名。
* `void`:根據請求路徑選擇一個默認的視圖名,移除前和尾的斜杠,并將其解析為一個視圖。當沒有提供視圖名(例如,返回模型屬性)或異步返回值(例如,`Mono<Void>`)時,也會發生相同的情況。
* `Rendering`:用例驅動的`API`用于視圖解析。
* `Model`,`Map`:請求向模型中添加的額外屬性。
* 其它:任何其他返回值(除了由`BeanUtils#isSimpleProperty`確定的簡單類型)都被視為添加到模型中的模型屬性。屬性名是通過使用約定從類名派生出來的,除非存在處理程序方法`@ModelAttribute`注解。
模型可以包含異步的、反應性的類型(例如,來自`Reactor`或`RxJava`)。在呈現之前,`AbstractView`將這些模型屬性解析為具體的值并更新模型。單值響應類型解析為單個值或沒有值(如果為空),而多值響應類型(例如`Flux<T>`)被收集并解析為`List<T>`。
配置視圖解析器很簡單,只需向`Spring`配置中添加一個`ViewResolutionResultHandler Bean`。
### 重定向
視圖名中的特殊`redirect:`前綴允許你執行重定向。`UrlBasedViewResolver`(及其子類)將此識別為需要重定向的指令。視圖名的其余部分是重定向`URL`。
實際效果與控制器返回`RedirectView`或`render.redirectto ("abc").build()`相同,但現在控制器本身可以根據邏輯視圖名稱進行操作。像`redirect:/some/resource`這樣的視圖名是相對于當前應用程序的,而像`redirect:https://example.com/arbitrary/path`這樣的視圖名則重定向到絕對`URL`。
### 異常
從`HandlerAdapter`返回的`HandlerResult`可以公開一個基于特定于處理程序的機制進行錯誤處理的函數。這個錯誤函數在以下情況被調用:
* 處理程序(例如`@Controller`)調用失敗。
* 通過`HandlerResultHandler`對處理程序返回值的處理失敗。
只要錯誤信號發生在處理程序返回的反應式式類型產生任何數據項之前,`error`函數可以更改響應(例如,變為錯誤狀態)
### 內容協商
`ViewResolutionResultHandler`支持內容協商。它將請求媒體類型與每個所選視圖支持的媒體類型進行比較。使用支持請求的媒體類型的第一個視圖。
為了支持`JSON`和`XML`等媒體類型,`Spring WebFlux`提供了`HttpMessageWriterView`,這是一個通過`HttpMessageWriter`呈現的特殊視圖。通常,你可以通過`WebFlux Configuration`將這些視圖配置為默認視圖。如果與請求的媒體類型匹配,則始終選擇并使用默認視圖。
- 1.反應式編程概述
- 2.Reactor框架
- Flux
- Mono
- 訂閱(Subscribe)
- 編程創建序列
- 線程和調度器
- 錯誤處理
- 3.Spring WebFlux概述
- 4.Spring WebFlux核心組件
- HttpHandler
- WebHandler
- ServerWebExchange
- 編碼和解碼器
- JSON
- Form Data
- Multipart Data
- 過濾器
- 異常處理器
- DispatcherHandler
- 5.Spring Boot啟動WebFlux
- 6.Spring WebFlux注解控制器
- 請求映射
- 處理程序方法
- 方法參數
- 返回值
- 類型轉換
- 模型(Model)
- 數據綁定(DataBinder)
- 異常管理
- @ControllerAdvice
- 7.Spring WebFlux函數端點
- HandlerFunction
- RouterFunction
- 運行服務
- 函數過濾器
- 8.Spring Boot中使用函數端點
- 9.Spring Webflux請求處理流程
- 10.Spring WebFlux配置
- 11.Spring WebFlux使用R2DBC訪問MySQL
- 12.Spring WebFlux訪問Redis
- 13.Spring WebFlux訪問MongoDB
- 14.Spring WebFlux集成Thymeleaf
- 15.Spring WebFlux集成FreeMarker
- 16.Spring WebFlux WebClient
- 17.Spring WebFlux WebSocket
- 18.測試
- 19.RSocket