DispatcherHandler

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

DispatcherHandler从 Spring 配置中发现它需要的委托组件。它还被设计为一个 Spring Bean 本身,并实现ApplicationContextAware以便访问其运行的上下文。如果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 处理程序 API 中的特殊 Bean 类型)。

Bean 类型 说明

HandlerMapping

将请求映射到处理程序。映射基于某些标准,其详细信息因HandlerMapping实现而异——带注解的控制器、简单的 URL 模式映射等。

主要的HandlerMapping实现是用于@RequestMapping带注解方法的RequestMappingHandlerMapping、用于功能端点路由的RouterFunctionMapping以及用于 URI 路径模式和WebHandler实例的显式注册的SimpleUrlHandlerMapping

HandlerAdapter

帮助DispatcherHandler调用映射到请求的处理程序,无论处理程序是如何实际调用的。例如,调用带注解的控制器需要解析注解。HandlerAdapter的主要目的是保护DispatcherHandler免受此类细节的影响。

HandlerResultHandler

处理处理程序调用结果并完成响应。请参阅结果处理

WebFlux 配置

应用程序可以声明处理请求所需的 Infrastructure Bean(列在Web 处理程序 APIDispatcherHandler下)。但是,在大多数情况下,WebFlux 配置是最佳起点。它声明了所需的 Bean 并提供了一个更高级别的配置回调 API 来对其进行自定义。

Spring Boot 依赖于 WebFlux 配置来配置 Spring WebFlux,并且还提供了许多其他便捷选项。

处理

DispatcherHandler按如下方式处理请求

  • 每个HandlerMapping都被要求查找匹配的处理程序,并使用第一个匹配项。

  • 如果找到处理程序,则将其通过适当的HandlerAdapter运行,后者将执行的返回值公开为HandlerResult

  • HandlerResult被提供给适当的HandlerResultHandler以通过直接写入响应或使用视图进行渲染来完成处理。

结果处理

通过HandlerAdapter调用处理程序的返回值与一些其他上下文一起包装为HandlerResult,并传递给第一个声明支持它的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 完成为空)时,也会发生同样的情况。

  • 渲染:视图解析场景的 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: 前缀作为结果。

内容协商

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

为了支持 JSON 和 XML 等媒体类型,Spring WebFlux 提供了 HttpMessageWriterView,这是一种通过HttpMessageWriter 渲染的特殊 View。通常,您会通过WebFlux 配置 将它们配置为默认视图。如果默认视图与请求的媒体类型匹配,则始终选择并使用它们。