Spring WebFlux, like Spring MVC, is designed in a single point of entry (front controller) pattern, where a central WebHandler, DispatcherHandler, provides the overall request processing algorithm, and the actual work is done by configurable components -delegates. This model is flexible and supports different workflows.

DispatcherHandler discovers the delegate beans it needs from the Spring configuration. It is also designed to act as a Spring bean and implements ApplicationContextAware to access the context in which it is running. If DispatcherHandler is declared with the bean name webHandler, then it is in turn discovered by WebHttpHandlerBuilder, which assembles the request processing chain.

The Spring configuration in a WebFlux application usually contains:

  • DispatcherHandler with bean name webHandler;

  • WebFilter and WebExceptionHandler beans;

  • Special DispatcherHandler beans;

  • And more.

The configuration is passed to WebHttpHandlerBuilder to build the chain processing as shown in the following example:

Java

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

val context: ApplicationContext = ...
val handler = WebHttpHandlerBuilder.applicationContext(context).build()

Received HttpHandler is ready for use with the server adapter.

1.3.1. Specialized types of beans

DispatcherHandler delegates to special beans the processing of requests and the issuance of appropriate responses. By "special beans" we mean Spring-managed Object instances that implement WebFlux framework contracts. They typically have built-in contracts, but you can customize their properties, extend them, or replace them.

The following table lists the special beans that are discovered by DispatcherHandler. Note that there are also some other bean types that are defined at a lower level.

Bean type Explanation

HandlerMapping

Maps a handler request. The mapping is based on some criteria, the details of which depend on the HandlerMapping implementation - annotated controllers, simple URL pattern mappings, etc.

Major HandlerMapping implementations are RequestMappingHandlerMapping for methods annotated with @RequestMapping, RouterFunctionMapping for endpoint functional routes, and SimpleUrlHandlerMapping for explicit template registration URI paths and WebHandler instances.

HandlerAdapter

Helps DispatcherHandler call the handler mapped to the request, regardless of how that handler is actually called. For example, calling an annotated controller requires annotation resolution. The main purpose of the HandlerAdapter is to shield the DispatcherHandler from such details.

HandlerResultHandler

Processes the result of the handler call and completes the response.

WebFlux configuration

Applications can declare infrastructure beans that are needed to process requests. However, in most cases the WebFlux configuration is the best starting point. It declares the required beans and provides a higher-level configuration callback API for configuration.

Spring Boot relies on WebFlux configuration to configure Spring WebFlux, and provides many additional convenient options.

1.3.3. Handling

DispatcherHandler processes requests as follows:

  • Each HandlerMapping is asked to find a suitable handler and is used the first match.

  • If a handler is found, it is executed through the corresponding HandlerAdapter, which exposes the return value after execution as HandlerResult.

  • HandlerResult is passed to the corresponding HandlerResultHandler to complete processing by writing to the response directly or using a rendering view.

1.3.4. Processing the results

The return value after calling the handler via the HandlerAdapter is wrapped as a HandlerResult, along with some additional context, and passed to the first HandlerResultHandler, which contains a statement about its support. The following table shows the available implementations of HandlerResultHandler, all of which are declared in the WebFlux configuration:

Result handler type Return values Default order

ResponseEntityResultHandler

ResponseEntity, typically from @Controller annotation instances.

0

ServerResponseResultHandler

ServerResponse, typically from functional endpoints.

0

ResponseBodyResultHandler

Processing return values from methods marked with the @ResponseBody annotation or classes marked with the @RestController annotation.

100

ViewResolutionResultHandler

CharSequence, View, Model, Map, Rendering or any other Object is considered a model attribute.

Integer.MAX_VALUE

Exceptions

The HandlerResult returned from the HandlerAdapter may expose a function for error handling based on some handler-specific mechanism. This error function is called if:

  • A call to a handler (for example, the @Controller annotation) fails.

  • Processing the handler's return value via HandlerResultHandler fails.

The error function can change the response (for example, to the error status), provided that the error signal occurs before the reactive type returned by the handler produces any data elements.

Methods annotated with @ExceptionHandler in classes annotated with @Controller are supported this way. In contrast, their support in Spring MVC is built on HandlerExceptionResolver. Usually this doesn't matter. However, be aware that WebFlux cannot use the @ControllerAdvice annotation to handle exceptions that occur before the handler is selected.

See: See also the "Exception Management" subsection in the "Annotated Controller" section or the "Exceptions" subsection in the WebHandler API section.

View Recognition

View recognition allows rendering in the browser using HTML -template and model, without tying you to a specific presentation technology. In Spring WebFlux, view recognition is supported by a special HandlerResultHandler that uses ViewResolver instances to map a string (representing the logical name of the view) to a View instance. The View is then used to render the response.

Processing

The HandlerResult passed to the ViewResolutionResultHandler contains the handler's return value and a model containing the attributes added during request processing. The return value is treated as one of the following:

  • String, CharSequence: The logical name of the view that should be resolved to View via a list of configured ViewResolver implementations.

  • void: Selects the default view name based on the path request, minus the leading and trailing slash, and is resolved in View. The same thing happens if no view name was specified (for example, a model attribute was returned) or there is an asynchronous return value (for example, Mono ended empty).

  • Rendering: API for view recognition scripts. Explore the capabilities of your IDE with code completion.

  • Model, Map: Additional model attributes that should be added to model for the request.

  • Any other: Any other return value (other than simple types defined by BeanUtils#isSimpleProperty) is considered a model attribute that must be added to the model. The attribute name is inferred from the class name using conventions if the @ModelAttribute handler method annotation is missing.

The model may contain asynchronous, reactive types (for example, from Reactor or RxJava). Before rendering, the AbstractView resolves such model attributes to concrete values and updates the model. Single-valued reactive types resolve to a single value or no value (if empty), and multi-valued reactive types (such as Flux<T>) are collected and resolved to List<T>.

Configuring view recognition is as simple as adding the ViewResolutionResultHandler bean to your Spring configuration. WebFlux configuration provides a dedicated configuration API for recognizing views.

Redirection

The special prefix redirect: in the view name allows redirection. UrlBasedViewResolver (and subclasses) recognizes this as an indication that a redirect is required. The rest of the view name is the redirect URL.

The net result is the same as if the controller had returned RedirectView or Rendering.redirectTo("abc").build(), but now the controller itself can operate on logical view names. A view name such as redirect:/some/resource is specific 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. This handler compares the media types of the request with the media types supported by each selected View. The first View that supports the requested media type(s) is used.

To support media types such as JSON and XML, Spring WebFlux provides a HttpMessageWriterView , which is a special View that renders via an HttpMessageWriter. Typically, these views are configured as default views through the WebFlux configuration. Default views are always selected and used if they match the requested media type.