You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
258 lines
12 KiB
258 lines
12 KiB
[[webflux-dispatcher-handler]] |
|
= `DispatcherHandler` |
|
|
|
[.small]#xref:web/webmvc/mvc-servlet.adoc[See equivalent in the Servlet stack]# |
|
|
|
Spring WebFlux, similarly to Spring MVC, is designed around the front controller pattern, |
|
where a central `WebHandler`, the `DispatcherHandler`, provides a shared algorithm for |
|
request processing, while actual work is performed by configurable, delegate components. |
|
This model is flexible and supports diverse workflows. |
|
|
|
`DispatcherHandler` discovers the delegate components it needs from Spring configuration. |
|
It is also designed to be a Spring bean itself and implements `ApplicationContextAware` |
|
for access to the context in which it runs. If `DispatcherHandler` is declared with a bean |
|
name of `webHandler`, it is, in turn, discovered by |
|
{api-spring-framework}/web/server/adapter/WebHttpHandlerBuilder.html[`WebHttpHandlerBuilder`], |
|
which puts together a request-processing chain, as described in xref:web/webflux/reactive-spring.adoc#webflux-web-handler-api[`WebHandler` API]. |
|
|
|
Spring configuration in a WebFlux application typically contains: |
|
|
|
* `DispatcherHandler` with the bean name `webHandler` |
|
* `WebFilter` and `WebExceptionHandler` beans |
|
* xref:web/webflux/dispatcher-handler.adoc#webflux-special-bean-types[`DispatcherHandler` special beans] |
|
* Others |
|
|
|
The configuration is given to `WebHttpHandlerBuilder` to build the processing chain, |
|
as the following example shows: |
|
|
|
[tabs] |
|
====== |
|
Java:: |
|
+ |
|
[source,java,indent=0,subs="verbatim,quotes",role="primary"] |
|
---- |
|
ApplicationContext context = ... |
|
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build(); |
|
---- |
|
|
|
Kotlin:: |
|
+ |
|
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] |
|
---- |
|
val context: ApplicationContext = ... |
|
val handler = WebHttpHandlerBuilder.applicationContext(context).build() |
|
---- |
|
====== |
|
|
|
The resulting `HttpHandler` is ready for use with a xref:web/webflux/reactive-spring.adoc#webflux-httphandler[server adapter]. |
|
|
|
|
|
|
|
[[webflux-special-bean-types]] |
|
== Special Bean Types |
|
[.small]#xref:web/webmvc/mvc-servlet/special-bean-types.adoc[See equivalent in the Servlet stack]# |
|
|
|
The `DispatcherHandler` delegates to special beans to process requests and render the |
|
appropriate responses. By "`special beans,`" we mean Spring-managed `Object` instances that |
|
implement WebFlux framework contracts. Those usually come with built-in contracts, but |
|
you can customize their properties, extend them, or replace them. |
|
|
|
The following table lists the special beans detected by the `DispatcherHandler`. Note that |
|
there are also some other beans detected at a lower level (see |
|
xref:web/webflux/reactive-spring.adoc#webflux-web-handler-api-special-beans[Special bean types] in the Web Handler API). |
|
|
|
[[webflux-special-beans-table]] |
|
[cols="1,2", options="header"] |
|
|=== |
|
| Bean type | Explanation |
|
|
|
| `HandlerMapping` |
|
| Map a request to a handler. The mapping is based on some criteria, the details of |
|
which vary by `HandlerMapping` implementation -- annotated controllers, simple |
|
URL pattern mappings, and others. |
|
|
|
The main `HandlerMapping` implementations are `RequestMappingHandlerMapping` for |
|
`@RequestMapping` annotated methods, `RouterFunctionMapping` for functional endpoint |
|
routes, and `SimpleUrlHandlerMapping` for explicit registrations of URI path patterns |
|
and `WebHandler` instances. |
|
|
|
| `HandlerAdapter` |
|
| Help the `DispatcherHandler` to invoke a handler mapped to a request regardless of |
|
how the handler is actually invoked. For example, invoking an annotated controller |
|
requires resolving annotations. The main purpose of a `HandlerAdapter` is to shield the |
|
`DispatcherHandler` from such details. |
|
|
|
| `HandlerResultHandler` |
|
| Process the result from the handler invocation and finalize the response. |
|
See xref:web/webflux/dispatcher-handler.adoc#webflux-resulthandling[Result Handling]. |
|
|
|
|=== |
|
|
|
|
|
|
|
[[webflux-framework-config]] |
|
== WebFlux Config |
|
[.small]#xref:web/webmvc/mvc-servlet/config.adoc[See equivalent in the Servlet stack]# |
|
|
|
Applications can declare the infrastructure beans (listed under |
|
xref:web/webflux/reactive-spring.adoc#webflux-web-handler-api-special-beans[Web Handler API] and |
|
xref:web/webflux/dispatcher-handler.adoc#webflux-special-bean-types[`DispatcherHandler`]) that are required to process requests. |
|
However, in most cases, the xref:web/webflux/dispatcher-handler.adoc#webflux-framework-config[WebFlux Config] is the best starting point. It declares the |
|
required beans and provides a higher-level configuration callback API to customize it. |
|
|
|
NOTE: Spring Boot relies on the WebFlux config to configure Spring WebFlux and also provides |
|
many extra convenient options. |
|
|
|
|
|
|
|
[[webflux-dispatcher-handler-sequence]] |
|
== Processing |
|
[.small]#xref:web/webmvc/mvc-servlet/sequence.adoc[See equivalent in the Servlet stack]# |
|
|
|
`DispatcherHandler` processes requests as follows: |
|
|
|
* Each `HandlerMapping` is asked to find a matching handler, and the first match is used. |
|
* If a handler is found, it is run through an appropriate `HandlerAdapter`, which |
|
exposes the return value from the execution as `HandlerResult`. |
|
* The `HandlerResult` is given to an appropriate `HandlerResultHandler` to complete |
|
processing by writing to the response directly or by using a view to render. |
|
|
|
|
|
|
|
[[webflux-resulthandling]] |
|
== Result Handling |
|
|
|
The return value from the invocation of a handler, through a `HandlerAdapter`, is wrapped |
|
as a `HandlerResult`, along with some additional context, and passed to the first |
|
`HandlerResultHandler` that claims support for it. The following table shows the available |
|
`HandlerResultHandler` implementations, all of which are declared in the xref:web/webflux/dispatcher-handler.adoc#webflux-framework-config[WebFlux Config]: |
|
|
|
[cols="1,2,1", options="header"] |
|
|=== |
|
| 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`, {api-spring-framework}/web/reactive/result/view/View.html[`View`], |
|
{api-spring-framework}/ui/Model.html[Model], `Map`, |
|
{api-spring-framework}/web/reactive/result/view/Rendering.html[Rendering], |
|
or any other `Object` is treated as a model attribute. |
|
|
|
See also xref:web/webflux/dispatcher-handler.adoc#webflux-viewresolution[View Resolution]. |
|
| `Integer.MAX_VALUE` |
|
|
|
|=== |
|
|
|
|
|
|
|
[[webflux-dispatcher-exceptions]] |
|
== Exceptions |
|
[.small]#xref:web/webmvc/mvc-servlet/exceptionhandlers.adoc[See equivalent in the Servlet stack]# |
|
|
|
`HandlerAdapter` implementations can handle internally exceptions from invoking a request |
|
handler, such as a controller method. However, an exception may be deferred if the request |
|
handler returns an asynchronous value. |
|
|
|
A `HandlerAdapter` may expose its exception handling mechanism as a |
|
`DispatchExceptionHandler` set on the `HandlerResult` it returns. When that's set, |
|
`DispatcherHandler` will also apply it to the handling of the result. |
|
|
|
A `HandlerAdapter` may also choose to implement `DispatchExceptionHandler`. In that case |
|
`DispatcherHandler` will apply it to exceptions that arise before a handler is mapped, |
|
e.g. during handler mapping, or earlier, e.g. in a `WebFilter`. |
|
|
|
See also xref:web/webflux/controller/ann-exceptions.adoc[Exceptions] in the "`Annotated Controller`" section or |
|
xref:web/webflux/reactive-spring.adoc#webflux-exception-handler[Exceptions] in the WebHandler API section. |
|
|
|
|
|
|
|
[[webflux-viewresolution]] |
|
== View Resolution |
|
[.small]#xref:web/webmvc/mvc-servlet/viewresolver.adoc[See equivalent in the Servlet stack]# |
|
|
|
View resolution enables rendering to a browser with an HTML template and a model without |
|
tying you to a specific view technology. In Spring WebFlux, view resolution is |
|
supported through a dedicated xref:web/webflux/dispatcher-handler.adoc#webflux-resulthandling[HandlerResultHandler] that uses |
|
`ViewResolver` instances to map a String (representing a logical view name) to a `View` |
|
instance. The `View` is then used to render the response. |
|
|
|
|
|
[[webflux-viewresolution-handling]] |
|
=== Handling |
|
[.small]#xref:web/webmvc/mvc-servlet/viewresolver.adoc#mvc-viewresolver-handling[See equivalent in the Servlet stack]# |
|
|
|
The `HandlerResult` passed into `ViewResolutionResultHandler` contains the return value |
|
from the handler and the model that contains attributes added during request |
|
handling. The return value is processed as one of the following: |
|
|
|
* `String`, `CharSequence`: A logical view name to be resolved to a `View` through |
|
the list of configured `ViewResolver` implementations. |
|
* `void`: Select a default view name based on the request path, minus the leading and |
|
trailing slash, and resolve it to a `View`. The same also happens when a view name |
|
was not provided (for example, model attribute was returned) or an async return value |
|
(for example, `Mono` completed empty). |
|
* {api-spring-framework}/web/reactive/result/view/Rendering.html[Rendering]: API for |
|
view resolution scenarios. Explore the options in your IDE with code completion. |
|
* `Model`, `Map`: Extra model attributes to be added to the model for the request. |
|
* Any other: Any other return value (except for simple types, as determined by |
|
{api-spring-framework}/beans/BeanUtils.html#isSimpleProperty-java.lang.Class-[BeanUtils#isSimpleProperty]) |
|
is treated as a model attribute to be added to the model. The attribute name is derived |
|
from the class name by using {api-spring-framework}/core/Conventions.html[conventions], |
|
unless a handler method `@ModelAttribute` annotation is present. |
|
|
|
The model can contain asynchronous, reactive types (for example, from Reactor or RxJava). Prior |
|
to rendering, `AbstractView` resolves such model attributes into concrete values |
|
and updates the model. Single-value reactive types are resolved to a single |
|
value or no value (if empty), while multi-value reactive types (for example, `Flux<T>`) are |
|
collected and resolved to `List<T>`. |
|
|
|
To configure view resolution is as simple as adding a `ViewResolutionResultHandler` bean |
|
to your Spring configuration. xref:web/webflux/config.adoc#webflux-config-view-resolvers[WebFlux Config] provides a |
|
dedicated configuration API for view resolution. |
|
|
|
See xref:web/webflux-view.adoc[View Technologies] for more on the view technologies integrated with Spring WebFlux. |
|
|
|
|
|
[[webflux-redirecting-redirect-prefix]] |
|
=== Redirecting |
|
[.small]#xref:web/webmvc/mvc-servlet/viewresolver.adoc#mvc-redirecting-redirect-prefix[See equivalent in the Servlet stack]# |
|
|
|
The special `redirect:` prefix in a view name lets you perform a redirect. The |
|
`UrlBasedViewResolver` (and sub-classes) recognize this as an instruction that a |
|
redirect is needed. The rest of the view name is the redirect URL. |
|
|
|
The net effect is the same as if the controller had returned a `RedirectView` or |
|
`Rendering.redirectTo("abc").build()`, but now the controller itself can |
|
operate in terms of logical view names. A view name such as |
|
`redirect:/some/resource` is relative to the current application, while a view name such as |
|
`redirect:https://example.com/arbitrary/path` redirects to an absolute URL. |
|
|
|
|
|
[[webflux-multiple-representations]] |
|
=== Content Negotiation |
|
[.small]#xref:web/webmvc/mvc-servlet/viewresolver.adoc#mvc-multiple-representations[See equivalent in the Servlet stack]# |
|
|
|
`ViewResolutionResultHandler` supports content negotiation. It compares the request |
|
media types with the media types supported by each selected `View`. The first `View` |
|
that supports the requested media type(s) is used. |
|
|
|
In order to support media types such as JSON and XML, Spring WebFlux provides |
|
`HttpMessageWriterView`, which is a special `View` that renders through an |
|
xref:web/webflux/reactive-spring.adoc#webflux-codecs[HttpMessageWriter]. Typically, you would configure these as default |
|
views through the xref:web/webflux/config.adoc#webflux-config-view-resolvers[WebFlux Configuration]. Default views are |
|
always selected and used if they match the requested media type. |
|
|
|
|
|
|
|
|
|
|