# 1.3 DispatcherHandler

Spring WebFlux与Spring MVC类似，是围绕前端控制器模式设计的，其中中央WebHandler DispatcherHandler提供了用于请求处理的共享算法，而实际工作是由可配置的委托组件执行的。该模型非常灵活，并支持多种工作流程。

DispatcherHandler从Spring配置中发现所需的委托组件。它还被设计为Spring Bean本身，并实现ApplicationContextAware来访问其运行的上下文。如果以WebHandler的bean名称声明了DispatcherHandler，则WebHttpHandlerBuilder会发现它，而WebHttpHandlerBuilder会将请求处理链组合在一起，如WebHandler API中所述。

WebFlux应用程序中的Spring配置通常包含：

* Bean名称为webHandler的DispatcherHandler
* WebFilter和WebExceptionHandler bean
* DispatcherHandler special beans

将配置提供给WebHttpHandlerBuilder以构建处理链，如以下示例所示：

```java
ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context);
```

生成的HttpHandler已准备好与服务器适配器一起使用。

## 1.3.1 Special Bean Types

| Bean type            | Explanation                                                                                                                                                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| HandlerMapping       | 将请求映射到处理程序。 映射基于某些条件，这些条件的详细信息因HandlerMapping实现而有所不同-带有注解的控制器，简单的URL模式映射以及其他。主要的HandlerMapping实现是用于@RequestMapping注解方法的RequestMappingHandlerMapping，用于功能端点路由的RouterFunctionMapping和用于URI路径模式和WebHandler实例的显式注册的SimpleUrlHandlerMapping。 |
| HandlerAdapter       | 帮助DispatcherHandler调用映射到请求的处理程序，而不管实际如何调用该处理程序。 例如，调用带注解的控制器需要解析注解。 HandlerAdapter的主要目的是使DispatcherHandler免受此类细节的影响。                                                                                                                    |
| HandlerResultHandler | 处理来自处理程序调用的结果，并最终确定响应。 请参阅结果处理。                                                                                                                                                                                                         |

## 1.3.2 WebFlux Config

应用程序可以声明处理请求所需的基础结构bean（在Web Handler API和DispatcherHandler下列出）。 但是，在大多数情况下，WebFlux Config是最佳起点。 它声明所需的bean，并提供更高级别的配置回调API对其进行自定义。

> Spring Boot依靠WebFlux配置来配置Spring WebFlux，并且还提供了许多额外的方便选项。

## 1.3.3 Processing

DispatcherHandler处理请求的方式如下：

* 要求每个HandlerMapping查找一个匹配的处理程序，并使用第一个匹配项。
* 如果找到处理程序，则通过适当的HandlerAdapter执行该处理程序，该处理程序将执行的返回值公开为HandlerResult。
* 通过直接写入响应或使用视图渲染，将HandlerResult提供给适当的HandlerResultHandler以完成处理。

## 1.3.4 Result Handling

通过HandlerAdapter调用处理程序的返回值连同其他一些上下文一起包装为HandlerResult，并传递给第一个支持该处理程序的HandlerResultHandler。 下表显示了可用的HandlerResultHandler实现，所有实现都在WebFlux Config中声明：

| Result Handler Type         | Return Values                                                                                   | Default Order      |
| --------------------------- | ----------------------------------------------------------------------------------------------- | ------------------ |
| ResponseEntityResultHandler | ResponseEntity, typically from @Controller instances.                                           | 0                  |
| ServerResponseResultHandler | ServerResponse, typically from functional endpoints.                                            | 0                  |
| ResponseBodyResultHandler   | Handle return values from @ResponseBody methods or @RestController classes.                     | 100                |
| ViewResolutionResultHandler | CharSequence, View, Model, Map, Rendering, or any other Object is treated as a model attribute. | Integer.MAX\_VALUE |

## 1.3.5 Exceptions

从HandlerAdapter返回的HandlerResult可以公开基于某些特定于处理程序的机制进行错误处理的函数。 在以下情况下将调用此错误函数：

* 处理程序（例如，@ Controller）调用失败。
* 通过HandlerResultHandler处理处理程序返回值失败。

只要在从处理程序返回的反应类型产生任何数据项之前发生错误信号，错误函数就可以更改响应（例如，更改为错误状态）。

这就是支持@Controller类中的@ExceptionHandler方法的方式。 相比之下，Spring MVC中对相同功能的支持建立在HandlerExceptionResolver之上。 这通常不重要。 但是，请记住，在WebFlux中，不能使用@ControllerAdvice来处理在选择处理程序之前发生的异常。

另请参见“带注解的控制器”部分中的“管理异常”或“ WebHandler API”部分中的“异常”。

## 1.3.6 View Resolution

View Resolution使您可以使用HTML模板和模型渲染到浏览器，而无需将您与特定的视图技术联系在一起。 在Spring WebFlux中，通过专用的HandlerResultHandler支持视图解析，该HandlerResultHandler使用ViewResolver实例将String（表示逻辑视图名称）映射到View实例。 然后使用View呈现响应。

**Handling**

传递给ViewResolutionResultHandler的HandlerResult包含处理程序的返回值和包含请求处理期间添加的属性的模型。返回值将作为以下值之一进行处理：

* 字符串，CharSequence：通过配置的ViewResolver实现列表解析为View的逻辑视图名称。
* void：根据请求路径选择默认视图名称，减去前导斜线和尾部斜杠，然后将其解析为视图。当未提供视图名称（例如，返回模型属性）或异步返回值（例如，Mono完成为空）时，也会发生同样的情况。
* Rendering：用于视图分辨率方案的API。通过代码完成探索IDE中的选项。
* Model, Map：额外的模型属性将添加到请求的模型中。
* Any other：任何其他返回值（由BeanUtils＃isSimpleProperty确定的简单类型除外）都将被视为要添加到模型的模型属性。属性名称是通过使用约定从类名称派生的，除非存在处理程序方法@ModelAttribute批注。

该模型可以包含异步，反应式类型（例如，来自Reactor或RxJava）。在渲染之前，AbstractView将此类模型属性解析为具体值并更新模型。单值反应类型被解析为单个值或无值（如果为空），而多值反应类型（例如Flux \<T>）被收集并解析为List \<T>。

配置视图分辨率就像在Spring配置中添加ViewResolutionResultHandler bean一样简单。 WebFlux Config提供了专用于视图分辨率的配置API。

有关与Spring WebFlux集成的视图技术的更多信息，请参见View Technologies。

**Redirecting**

视图名称中的特殊redirect：前缀使您可以执行重定向。 UrlBasedViewResolver（和子类）将其识别为需要重定向的指令。 视图名称的其余部分是重定向URL。

最终效果与控制器已返回RedirectView或Rendering.redirectTo（“ abc”）。build（）相同，但是现在控制器本身可以根据逻辑视图名称进行操作。 视图名称（例如redirect：/ some / resource）是相对于当前应用程序的，而视图名称（例如redirect：https：//example.com/arbitrary/path）将重定向到绝对URL。

**Content Negotiation**

ViewResolutionResultHandler支持内容协商。 它将请求媒体类型与每个选定视图支持的媒体类型进行比较。 使用支持请求的媒体类型的第一个视图。

为了支持JSON和XML之类的媒体类型，Spring WebFlux提供了HttpMessageWriterView，这是一个通过HttpMessageWriter呈现的特殊视图。 通常，您可以通过WebFlux配置将其配置为默认视图。 如果默认视图与请求的媒体类型匹配，则始终会选择和使用它们。
