跳到主要内容

DispatcherHandler

ChatGPT-4o 中英对照 DispatcherHandler DispatcherHandler

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

DispatcherHandler 从 Spring 配置中发现其所需的委托组件。它也被设计为一个 Spring bean 本身,并实现了 ApplicationContextAware 接口以访问其运行的上下文。如果 DispatcherHandler 被声明为一个名为 webHandler 的 bean,那么 WebHttpHandlerBuilder 将会发现它,并如 WebHandler API 中所述,组装一个请求处理链。

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

配置被提供给 WebHttpHandlerBuilder 以构建处理链,如下例所示:

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

生成的 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,并附加一些额外的上下文,然后传递给第一个声称支持它的 HandlerResultHandler。下表显示了可用的 HandlerResultHandler 实现,所有这些都在 WebFlux 配置 中声明:

结果处理器类型返回值默认顺序
ResponseEntityResultHandlerResponseEntity,通常来自 @Controller 实例。0
ServerResponseResultHandlerServerResponse,通常来自功能性端点。0
ResponseBodyResultHandler处理来自 @ResponseBody 方法或 @RestController 类的返回值。100
ViewResolutionResultHandlerCharSequenceViewModelMapRendering 或任何其他 Object 被视为模型属性。

另请参见 视图解析
Integer.MAX_VALUE

异常

HandlerAdapter 实现可以在内部处理调用请求处理器(例如控制器方法)时产生的异常。然而,如果请求处理器返回一个异步值,异常可能会被延迟处理。

一个 HandlerAdapter 可以将其异常处理机制作为 DispatchExceptionHandler 暴露,并设置在它返回的 HandlerResult 上。当设置了这个时,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 配置 提供了一个专用的视图解析配置 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,这是一种通过 HttpMessageWriter 渲染的特殊 View。通常,你可以通过 WebFlux 配置 将这些配置为默认视图。如果默认视图与请求的媒体类型匹配,则总是会被选择和使用。