Skip to content

Commit

Permalink
Docs: result handling and view resolution
Browse files Browse the repository at this point in the history
Issue: SPR-16393
  • Loading branch information
rstoyanchev committed Jan 27, 2018
1 parent fbde97f commit 00b95b1
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
* <li>{@link View} -- View to render with
* <li>{@link Model} -- attributes to add to the model
* <li>{@link Map} -- attributes to add to the model
* <li>{@link Rendering} -- use case driven API for view resolution</li>
* <li>{@link ModelAttribute @ModelAttribute} -- attribute for the model
* <li>Non-simple value -- attribute for the model
* </ul>
Expand Down
144 changes: 121 additions & 23 deletions src/docs/asciidoc/web/webflux.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,11 @@ ApplicationContext context = ...
HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context).build()
----



[[webflux-web-handler-api-special-beans]]
==== Special bean types

The table below lists the components that `WebHttpHandlerBuilder` detects:

[cols="2,2,1,3", options="header"]
Expand Down Expand Up @@ -443,7 +448,7 @@ then exposed through methods on `ServerWebExchange`.


[[webflux-form-data]]
==== Form Reader
==== Form data

`ServerWebExchange` exposes the following method for access to form data:
[source,java,indent=0]
Expand All @@ -459,7 +464,7 @@ The `DefaultServerWebExchange` uses the configured `HttpMessageReader` to parse


[[webflux-multipart]]
==== Multipart Reader
==== Multipart data
[.small]#<<web.adoc#mvc-multipart,Same in Spring MVC>>#

`ServerWebExchange` exposes the following method for access to multipart data:
Expand Down Expand Up @@ -587,10 +592,13 @@ The resulting `HttpHandler` is ready for use with a
[.small]#<<web.adoc#mvc-servlet-special-bean-types,Same in Spring MVC>>#

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 one of the framework contracts listed in the table below.
Spring WebFlux provides built-in implementations of these contracts but you can also
customize, extend, or replace them.
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 then, or replaced.

The table below 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.

[[webflux-special-beans-table]]
[cols="1,2", options="header"]
Expand All @@ -602,10 +610,10 @@ customize, extend, or replace them.
which vary by `HandlerMapping` implementation -- annotated controllers, simple
URL pattern mappings, etc.

The main `HandlerMapping` implementations are `RequestMappingHandlerMapping` based on
`@RequestMapping` annotated methods, `RouterFunctionMapping` based on functional
endpoint routes, and `SimpleUrlHandlerMapping` based on explicit registrations of URI
path patterns to handlers.
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``'s.

| HandlerAdapter
| Help the `DispatcherHandler` to invoke a handler mapped to a request regardless of
Expand All @@ -615,25 +623,27 @@ customize, extend, or replace them.

| HandlerResultHandler
| Process the result from the handler invocation and finalize the response.
See <<webflux-resulthandling>>.

The built-in `HandlerResultHandler` implementations are `ResponseEntityResultHandler`
supporting `ResponseEntity` return values, `ResponseBodyResultHandler`
supporting `@ResponseBody` methods, `ServerResponseResultHandler`
supporting the `ServerResponse` returned from functional endpoints, and
`ViewResolutionResultHandler` supporting rendering with a view and a model.
|===



[[webflux-framework-config]]
=== Framework Config
=== WebFlux Config
[.small]#<<web.adoc#mvc-servlet-config,Same in Spring MVC>>#

The `DispatcherHandler` detects the special beans it needs in the `ApplicationContext`.
Applications can declare the special beans they wish to have. However most applications
will find a better starting point in the WebFlux Java config which provide a higher level
configuration API that in turn make the necessary bean declarations.
See <<webflux-config>> for more details.
Applications can declare the infrastructure beans listed under
<<webflux-web-handler-api-special-beans,Web Handler API>> and
<<webflux-special-bean-types,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.

[NOTE]
====
Spring Boot relies on the WebFlux config to configure Spring WebFlux and also provides
many extra convenient options.
====



Expand All @@ -651,6 +661,94 @@ processing by writing to the response directly or using a view to render.



[[webflux-resulthandling]]
=== Result Handling

When `DispatcherHandler` needs to process the return value from a handler, it finds a
`HandlerResultHandler` that support it and invokes it. The available implementations are
listed below with their default order (all are declared in the <<webflux-config>>):

* `ResponseEntityResultHandler` -- handles `ResponseEntity` return values typically
returned from annotated controllers. The order is set to 0 since it safely matches return
values by type.
* `ServerResponseResultHandler` -- supports `ServerResponse` return values typically
returned from functional endpoints. The order is set to 0 since it safely matches return
values by type.
* `ResponseBodyResultHandler` -- handles return values from `@ResponseBody` methods or
`@RestController` classes. The order is set to 100, i.e. after result handlers that
check for a specific type.
* `ViewResolutionResultHandler` -- performs the <<webflux-viewresolution>> algorithm for
HTML template rendering. The order is set to `Ordered.LOWEST_PRECEDENCE` since it
supports several specific types, e.g. `String`, `Map`, `Rendering`, and others, but will
also treat any other Object as a model attribute. This is why it needs to be last in
the order.



[[webflux-viewresolution]]
=== View Resolution
[.small]#<<web.adoc#mvc-viewresolver,Same in Spring MVC>>#

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 the `ViewResolutionResultHandler` that relies on a list of
``ViewResolver``'s to map a String-based view name to a `View` to render the response
with. The <<webflux-config-view-resolvers,WebFlux Config>> can be used to configure the
view resolvers to use.

The `HandlerResult` passed into `ViewResolutionResultHandler` contains the return value
along with a map of attributes (i.e. the model) from the handler. The return value is
then processed as one of the following:

* `String`, `CharSequence` -- a logical view name to be resolved to a `View` through
the list of configured ``ViewResolver``'s.
* `void` or no value (e.g. model attribute returned) -- select default view name based on
the request path minus the leading and trailing slash, and the resolved to a `View`.
* `Model`, `Map` -- attributes to be added to the model.
* {api-spring-framework}/web/reactive/result/view/Rendering.html[Rendering] -- API for
view resolution scenarios; easiest to explore the options with code completion.
* Other -- attribute to be added to the model; the name of the attribute is derived using
Class name conventions, or from a handler method `@ModelAttribute` annotation if present.

The model can contain asynchronous, reactive types (e.g. from Reactor, RxJava). Prior
to rendering, `AbstractView` resolves such model attributes into their 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, e.g. `Flux<T>` are
collected and resolved to `List<T>`.


[[webflux-redirecting-redirect-prefix]]
==== Redirect
[.small]#<<web.adoc#mvc-redirecting-redirect-prefix,Same in Spring MVC>>#

The special `redirect:` prefix in a view name allows you to 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 simply
operate in terms of logical view names. A view name such as
`redirect:/some/resource` is relative to the current application, while the view name
`redirect:http://example.com/arbitrary/path` redirects to an absolute URL.


[[webflux-multiple-representations]]
==== Content negotiation
[.small]#<<web.adoc#mvc-multiple-representations,Same in Spring MVC>>#

`ViewResolutionResultHandler` supports content negotiation. It compares the request
media type(s) with the media type(s) 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
<<webflux-codecs,HttpMessageWriter>>. Typically you would configure these as default
views through the <<webflux-config-view-resolvers,WebFlux Config>>. Default views are
always selected and used if they match the requested media type.




[[webflux-controller]]
== Annotated Controllers
[.small]#<<web.adoc#mvc-controller,Same in Spring MVC>>#
Expand Down Expand Up @@ -1105,12 +1203,12 @@ generally supported for all return values.
|Controller method return value|Description

|`@ResponseBody`
|The return value is encoded through ``HttpMessageWriter``s and written to the response.
|The return value is encoded through ``HttpMessageWriter``'s and written to the response.
See <<webflux-ann-responsebody>>.

|`HttpEntity<B>`, `ResponseEntity<B>`
|The return value specifies the full response including HTTP headers and body be encoded
through ``HttpMessageWriter``s and written to the response.
through ``HttpMessageWriter``'s and written to the response.
See <<webflux-ann-responseentity>>.

|`HttpHeaders`
Expand Down
43 changes: 24 additions & 19 deletions src/docs/asciidoc/web/webmvc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,11 @@ If an application context hierarchy is not required, applications may configure
[.small]#<<web-reactive.adoc#webflux-special-bean-types,Same in Spring WebFlux>>#

The `DispatcherServlet` delegates to special beans to process requests and render the
appropriate responses. By "special beans" we mean Spring-managed Object instances that
implement one of the framework contracts listed in the table below.
Spring MVC provides built-in implementations of these contracts but you can also
customize, extend, or replace them.
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 then, or replaced.

The table below lists the special beans detected by the `DispatcherHandler`:

[[mvc-webappctx-special-beans-tbl]]
[cols="1,2", options="header"]
Expand Down Expand Up @@ -273,28 +274,29 @@ customize, extend, or replace them.


[[mvc-servlet-config]]
=== Framework Config
=== Web MVC Config
[.small]#<<web-reactive.adoc#webflux-framework-config,Same in Spring WebFlux>>#

For each type of special bean, the `DispatcherServlet` checks for the `WebApplicationContext` first.
If there are no matching bean types, it falls back on the default types listed in
Applications can declare the infrastructure beans listed in <<mvc-special-bean-types>>
that are required to process requests. The `DispatcherServlet` checks the
`WebApplicationContext` for each special bean. If there are no matching bean types, it
falls back on the default types listed in
https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties[DispatcherServlet.properties].

Applications can declare the special beans they wish to have. Most applications however
will find a better starting point in the MVC Java config or the MVC XML namespace which
provide a higher level configuration API that in turn make the necessary bean declarations.
See <<mvc-config>> for more details.
In most cases the <<mvc-config>> is the best starting point. It declares the required
beans in either Java or XML, and provides a higher level configuration callback API to
customize it.

[NOTE]
====
Spring Boot relies on the MVC Java config to configure Spring MVC and also
provides many extra convenient options on top.
provides many extra convenient options.
====



[[mvc-container-config]]
=== Container Config
=== Servlet Config

In a Servlet 3.0+ environment, you have the option of configuring the Servlet container
programmatically as an alternative or in combination with a `web.xml` file. Below is an
Expand Down Expand Up @@ -506,6 +508,7 @@ declare it as an <<mvc-ann-controller-advice>> bean or configure it directly on

[[mvc-viewresolver]]
=== View Resolution
[.small]#<<web-reactive.adoc#webflux-viewresolution,Same in Spring WebFlux>>#

Spring MVC defines the `ViewResolver` and `View` interfaces that enable you to render
models in a browser without tying you to a specific view technology. `ViewResolver`
Expand Down Expand Up @@ -569,17 +572,18 @@ indicate the view could not be found. However in the case of JSPs, and
perform a dispatch through `RequestDispatcher`. There an `InternalResourceViewResolver`
must always be configured last in the order.

See <<mvc-config-view-controller,View Controllers>> under <<mvc-config>> for details on
how to configure view resolution. Also see<<mvc-view>> for more details on supported
view technologies.
See <<mvc-config-view-resolvers>> and <<mvc-config-view-controller,View Controllers>>
under <<mvc-config>> for details on how to configure view resolution. Also see
<<mvc-view>> for more details on supported view technologies.


[[mvc-redirecting-redirect-prefix]]
==== Redirect
[.small]#<<web-reactive.adoc#webflux-redirecting-redirect-prefix,Same in Spring WebFlux>>#

The special `redirect:` prefix in a view name allows you to perform a redirect. The
`UrlBasedViewResolver` (and subclasses) will recognize this as a special indication that a
redirect is needed. The rest of the view name will be treated as the redirect URL.
`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`, but now
the controller itself can simply operate in terms of logical view names. A logical view
Expand All @@ -605,6 +609,7 @@ Servlet/JSP engine. Note that you may also chain multiple view resolvers, instea

[[mvc-multiple-representations]]
==== Content negotiation
[.small]#<<web-reactive.adoc#webflux-multiple-representations,Same in Spring WebFlux>>#

{api-spring-framework}/web/servlet/view/ContentNegotiatingViewResolver.html[ContentNegotiatingViewResolver]
does not resolve views itself but rather delegates
Expand Down Expand Up @@ -3481,7 +3486,7 @@ The async request processing feature must be enabled at the Servlet container le
The MVC config also exposes several options for asynchronous requests.


[[mvc-ann-async-configuration-spring-mvc]]
[[mvc-ann-async-configuration-servlet3]]
==== Servlet container

Filter and Servlet declarations have an `asyncSupported` that needs to be set to true
Expand Down

0 comments on commit 00b95b1

Please sign in to comment.