DispatcherHandler
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
WebHttpHandlerBuilder
,
which puts together a request-processing chain, as described in webflux-web-handler-api.
Spring configuration in a WebFlux application typically contains:
-
DispatcherHandler
with the bean name,webHandler
-
WebFilter
andWebExceptionHandler
beans -
Others
The configuration is given to WebHttpHandlerBuilder
to build the processing chain,
as the following example shows:
ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build();
val context: ApplicationContext = ...
val handler = WebHttpHandlerBuilder.applicationContext(context).build()
The resulting HttpHandler
is ready for use with a server adapter.
Special Bean Types
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
webflux-web-handler-api-special-beans in the Web Handler API).
Bean type | Explanation |
---|---|
|
Map a request to a handler. The mapping is based on some criteria, the details of
which vary by The main |
|
Help the |
|
Process the result from the handler invocation and finalize the response. See webflux-resulthandling. |
WebFlux Config
Applications can declare the infrastructure beans (listed under
Web Handler API and
DispatcherHandler
) that are required to process requests.
However, in most cases, the webflux-config is the best starting point. It declares the
required beans and provides a higher-level configuration callback API to customize it.
Spring Boot relies on the WebFlux config to configure Spring WebFlux and also provides many extra convenient options. |
Processing
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 executed through an appropriate
HandlerAdapter
, which exposes the return value from the execution asHandlerResult
. -
The
HandlerResult
is given to an appropriateHandlerResultHandler
to complete processing by writing to the response directly or by using a view to render.
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 webflux-config:
Result Handler Type | Return Values | Default Order |
---|---|---|
|
|
0 |
|
|
0 |
|
Handle return values from |
100 |
|
See also webflux-viewresolution. |
|
Exceptions
The HandlerResult
returned from a HandlerAdapter
can expose a function for error
handling based on some handler-specific mechanism. This error function is called if:
-
The handler (for example,
@Controller
) invocation fails. -
The handling of the handler return value through a
HandlerResultHandler
fails.
The error function can change the response (for example, to an error status), as long as an error signal occurs before the reactive type returned from the handler produces any data items.
This is how @ExceptionHandler
methods in @Controller
classes are supported.
By contrast, support for the same in Spring MVC is built on a HandlerExceptionResolver
.
This generally should not matter. However, keep in mind that, in WebFlux, you cannot use a
@ControllerAdvice
to handle exceptions that occur before a handler is chosen.
See also webflux-ann-controller-exceptions in the “Annotated Controller” section or webflux-exception-handler in the WebHandler API section.
View Resolution
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 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.
Handling
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 aView
through the list of configuredViewResolver
implementations. -
void
: Select a default view name based on the request path, minus the leading and trailing slash, and resolve it to aView
. 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). -
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 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 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. WebFlux Config provides a
dedicated configuration API for view resolution.
See webflux-view for more on the view technologies integrated with Spring WebFlux.
Redirecting
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.
Content Negotiation
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
HttpMessageWriter. Typically, you would configure these as default
views through the WebFlux Configuration. Default views are
always selected and used if they match the requested media type.