259 lines
12 KiB
Plaintext
259 lines
12 KiB
Plaintext
[[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.
|
|
|
|
|
|
|
|
|