Doc use of reactive types in Spring MVC controllers
Issue: SPR-15365
This commit is contained in:
parent
f716c8e9bc
commit
f293c4d84b
|
|
@ -34,7 +34,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* types, in arbitrary order (except for validation results, which need to
|
||||
* follow right after the corresponding command object, if desired):
|
||||
* <ul>
|
||||
* <li>Request and/or response objects (typically from the Servlet API).
|
||||
* <li>Request and/or response objects from the Servlet API.
|
||||
* You may choose any specific request/response type, e.g.
|
||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}.
|
||||
* <li>Session object: typically {@link javax.servlet.http.HttpSession}.
|
||||
|
|
@ -60,7 +60,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* the response's content. This will be the raw OutputStream/Writer as
|
||||
* exposed by the Servlet API.
|
||||
* <li>{@link org.springframework.http.HttpMethod} for the HTTP request method</li>
|
||||
* <li>{@link PathVariable @PathVariable} annotated parameters (Servlet-only)
|
||||
* <li>{@link PathVariable @PathVariable} annotated parameters
|
||||
* for access to URI template values (i.e. /hotels/{hotel}). Variable values will be
|
||||
* converted to the declared method argument type. By default, the URI template
|
||||
* will match against the regular expression {@code [^\.]*} (i.e. any character
|
||||
|
|
@ -69,7 +69,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* Additionally, {@code @PathVariable} can be used on a
|
||||
* {@link java.util.Map Map<String, String>} to gain access to all
|
||||
* URI template variables.
|
||||
* <li>{@link MatrixVariable @MatrixVariable} annotated parameters (Servlet-only)
|
||||
* <li>{@link MatrixVariable @MatrixVariable} annotated parameters
|
||||
* for access to name-value pairs located in URI path segments. Matrix variables
|
||||
* must be represented with a URI template variable. For example /hotels/{hotel}
|
||||
* where the incoming URL may be "/hotels/42;q=1".
|
||||
|
|
@ -89,7 +89,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}, or
|
||||
* {@link org.springframework.http.HttpHeaders HttpHeaders} method parameter to
|
||||
* gain access to all request headers.
|
||||
* <li>{@link RequestBody @RequestBody} annotated parameters (Servlet-only)
|
||||
* <li>{@link RequestBody @RequestBody} annotated parameters
|
||||
* for access to the Servlet request HTTP contents. The request stream will be
|
||||
* converted to the declared method argument type using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
|
|
@ -98,9 +98,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* {@link org.springframework.validation.Errors} argument.
|
||||
* Instead a {@link org.springframework.web.bind.MethodArgumentNotValidException}
|
||||
* exception is raised.
|
||||
* <li>{@link RequestPart @RequestPart} annotated parameters
|
||||
* (Servlet-only, {@literal @MVC 3.1-only})
|
||||
* for access to the content
|
||||
* <li>{@link RequestPart @RequestPart} annotated parameters for access to the content
|
||||
* of a part of "multipart/form-data" request. The request part stream will be
|
||||
* converted to the declared method argument type using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
|
|
@ -116,15 +114,15 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* <li>{@link RequestAttribute @RequestAttribute} annotated parameters for access
|
||||
* to request attributes.
|
||||
* <li>{@link org.springframework.http.HttpEntity HttpEntity<?>} parameters
|
||||
* (Servlet-only) for access to the Servlet request HTTP headers and contents.
|
||||
* for access to the Servlet request HTTP headers and contents.
|
||||
* The request stream will be converted to the entity body using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
* converters}.
|
||||
* <li>{@link java.util.Map} / {@link org.springframework.ui.Model} /
|
||||
* {@link org.springframework.ui.ModelMap} for enriching the implicit model
|
||||
* that will be exposed to the web view.
|
||||
* <li>{@link org.springframework.web.servlet.mvc.support.RedirectAttributes}
|
||||
* (Servlet-only, {@literal @MVC 3.1-only}) to specify the exact set of attributes
|
||||
* <li>{@link org.springframework.web.servlet.mvc.support.RedirectAttributes},
|
||||
* to specify the exact set of attributes
|
||||
* to use in case of a redirect and also to add flash attributes (attributes
|
||||
* stored temporarily on the server-side to make them available to the request
|
||||
* after the redirect). {@code RedirectAttributes} is used instead of the
|
||||
|
|
@ -147,7 +145,6 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* attributes that have been indicated by the {@link SessionAttributes @SessionAttributes}
|
||||
* annotation at the handler type level).
|
||||
* <li>{@link org.springframework.web.util.UriComponentsBuilder}
|
||||
* (Servlet-only, {@literal @MVC 3.1-only})
|
||||
* for preparing a URL relative to the current request's host, port, scheme,
|
||||
* context path, and the literal part of the servlet mapping.
|
||||
* </ul>
|
||||
|
|
@ -160,64 +157,63 @@ import org.springframework.core.annotation.AliasFor;
|
|||
*
|
||||
* <p>The following return types are supported for handler methods:
|
||||
* <ul>
|
||||
* <li>A {@code ModelAndView} object (from Servlet MVC),
|
||||
* <li>{@code ModelAndView} object (from Servlet MVC),
|
||||
* with the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link org.springframework.ui.Model Model} object, with the view name implicitly
|
||||
* <li>{@link org.springframework.ui.Model Model} object, with the view name implicitly
|
||||
* determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* and the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link java.util.Map} object for exposing a model,
|
||||
* <li>{@link java.util.Map} object for exposing a model,
|
||||
* with the view name implicitly determined through a
|
||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* and the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link org.springframework.web.servlet.View} object, with the
|
||||
* <li>{@link org.springframework.web.servlet.View} object, with the
|
||||
* model implicitly determined through command objects and
|
||||
* {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* The handler method may also programmatically enrich the model by
|
||||
* declaring a {@link org.springframework.ui.Model} argument (see above).
|
||||
* <li>A {@link String} value which is interpreted as view name,
|
||||
* <li>{@link String} value which is interpreted as view name,
|
||||
* with the model implicitly determined through command objects and
|
||||
* {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* The handler method may also programmatically enrich the model by
|
||||
* declaring a {@link org.springframework.ui.ModelMap} argument
|
||||
* (see above).
|
||||
* <li>{@link ResponseBody @ResponseBody} annotated methods (Servlet-only)
|
||||
* <li>{@link ResponseBody @ResponseBody} annotated methods
|
||||
* for access to the Servlet response HTTP contents. The return value will
|
||||
* be converted to the response stream using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
* converters}.
|
||||
* <li>An {@link org.springframework.http.HttpEntity HttpEntity<?>} or
|
||||
* <li>{@link org.springframework.http.HttpEntity HttpEntity<?>} or
|
||||
* {@link org.springframework.http.ResponseEntity ResponseEntity<?>} object
|
||||
* (Servlet-only) to access to the Servlet response HTTP headers and contents.
|
||||
* to access to the Servlet response HTTP headers and contents.
|
||||
* The entity body will be converted to the response stream using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
* converters}.
|
||||
* <li>An {@link org.springframework.http.HttpHeaders HttpHeaders} object to
|
||||
* <li>{@link org.springframework.http.HttpHeaders HttpHeaders} object to
|
||||
* return a response with no body.</li>
|
||||
* <li>A {@link Callable} which is used by Spring MVC to obtain the return
|
||||
* value asynchronously in a separate thread transparently managed by Spring MVC
|
||||
* on behalf of the application.
|
||||
* <li>A {@link org.springframework.web.context.request.async.DeferredResult}
|
||||
* which the application uses to produce a return value in a separate
|
||||
* thread of its own choosing, as an alternative to returning a Callable.
|
||||
* <li>A {@link org.springframework.util.concurrent.ListenableFuture}
|
||||
* which the application uses to produce a return value in a separate
|
||||
* thread of its own choosing, as an alternative to returning a Callable.
|
||||
* <li>A {@link java.util.concurrent.CompletionStage} (implemented by
|
||||
* {@link java.util.concurrent.CompletableFuture} for example)
|
||||
* which the application uses to produce a return value in a separate
|
||||
* thread of its own choosing, as an alternative to returning a Callable.
|
||||
* <li>A {@link org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter}
|
||||
* can be used to write multiple objects to the response asynchronously;
|
||||
* also supported as the body within {@code ResponseEntity}.</li>
|
||||
* <li>An {@link org.springframework.web.servlet.mvc.method.annotation.SseEmitter}
|
||||
* can be used to write Server-Sent Events to the response asynchronously;
|
||||
* also supported as the body within {@code ResponseEntity}.</li>
|
||||
* <li>A {@link org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody}
|
||||
* can be used to write to the response asynchronously;
|
||||
* also supported as the body within {@code ResponseEntity}.</li>
|
||||
* <li>{@link Callable} -- async computation in a Spring MVC managed thread.</li>
|
||||
* <li>{@link org.springframework.web.context.request.async.DeferredResult DeferredResult} --
|
||||
* async result produced later from an application managed, or any thread.
|
||||
* <li>{@link org.springframework.util.concurrent.ListenableFuture ListenableFuture}
|
||||
* alternative, equivalent to {@code DeferredResult}.</li>
|
||||
* <li>{@link java.util.concurrent.CompletionStage CompletionStage} and
|
||||
* {@link java.util.concurrent.CompletableFuture CompletableFuture} --
|
||||
* alternative, equivalent to {@code DeferredResult}.</li>
|
||||
* <li>{@link org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter} --
|
||||
* {@code @ResponseBody}-style, asynchronous writing of a stream of Objects to the
|
||||
* response body.</li>
|
||||
* <li>{@link org.springframework.web.servlet.mvc.method.annotation.SseEmitter} --
|
||||
* variant of {@code ResponseBodyEmitter} for a Server-Sent Events formatted stream.</li>
|
||||
* <li>{@link org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody} --
|
||||
* async writing directly to the response body {@link java.io.OutputStream}.</li>
|
||||
* <li>Reactive types (e.g. Reactor {@code Flux}/{@code Mono}, RxJava 1 & 2
|
||||
* {@code Observable}/{@code Single}, or others via
|
||||
* {@link org.springframework.core.ReactiveAdapterRegistry ReactiveAdapterRegistry}) --
|
||||
* alternatives, equivalent to {@code DeferredResult} or {@code ResponseBodyEmitter}
|
||||
* and {@code SseEmitter} depending also on the requested media types (e.g.
|
||||
* "text/event-stream", "application/json+stream").</li>
|
||||
* <li>{@code void} if the method handles the response itself (by
|
||||
* writing the response content directly, declaring an argument of type
|
||||
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,11 @@ public class AsyncSupportConfigurer {
|
|||
* highly recommended to change that default in production since the simple
|
||||
* executor does not re-use threads.
|
||||
*
|
||||
* <p>As of 5.0 this executor is also used when a controller returns a reactive
|
||||
* type that does streaming (e.g. "text/event-stream" or
|
||||
* "application/stream+json") for the blocking writes to the
|
||||
* {@link javax.servlet.ServletOutputStream}.
|
||||
*
|
||||
* @param taskExecutor the task executor instance to use by default
|
||||
*/
|
||||
public AsyncSupportConfigurer setTaskExecutor(AsyncTaskExecutor taskExecutor) {
|
||||
|
|
|
|||
|
|
@ -231,9 +231,14 @@
|
|||
<xsd:attribute name="task-executor" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation source="java:org.springframework.core.task.AsyncTaskExecutor"><![CDATA[
|
||||
The bean name of a default AsyncTaskExecutor to use when a controller method returns a {@link Callable}.
|
||||
The bean name of a default AsyncTaskExecutor to use when a controller method returns a "Callable".
|
||||
Controller methods can override this default on a per-request basis by returning an AsyncTask.
|
||||
By default, a SimpleAsyncTaskExecutor is used which does not re-use threads and is not recommended for production.
|
||||
|
||||
As of 5.0 this executor is also used when a controller returns a reactive type that does streaming
|
||||
(e.g. "text/event-stream" or "application/stream+json") for the blocking writes to the
|
||||
"javax.servlet.ServletOutputStream".
|
||||
|
||||
]]></xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
|
|
|
|||
|
|
@ -1408,18 +1408,18 @@ of `java.util.Optional` in those cases is equivalent to having `required=false`.
|
|||
==== Supported method return types
|
||||
The following are the supported return types:
|
||||
|
||||
* A `ModelAndView` object, with the model implicitly enriched with command objects and
|
||||
* `ModelAndView` object, with the model implicitly enriched with command objects and
|
||||
the results of `@ModelAttribute` annotated reference data accessor methods.
|
||||
* A `Model` object, with the view name implicitly determined through a
|
||||
* `Model` object, with the view name implicitly determined through a
|
||||
`RequestToViewNameTranslator` and the model implicitly enriched with command objects
|
||||
and the results of `@ModelAttribute` annotated reference data accessor methods.
|
||||
* A `Map` object for exposing a model, with the view name implicitly determined through
|
||||
* `Map` object for exposing a model, with the view name implicitly determined through
|
||||
a `RequestToViewNameTranslator` and the model implicitly enriched with command objects
|
||||
and the results of `@ModelAttribute` annotated reference data accessor methods.
|
||||
* A `View` object, with the model implicitly determined through command objects and
|
||||
* `View` object, with the model implicitly determined through command objects and
|
||||
`@ModelAttribute` annotated reference data accessor methods. The handler method may
|
||||
also programmatically enrich the model by declaring a `Model` argument (see above).
|
||||
* A `String` value that is interpreted as the logical view name, with the model
|
||||
* `String` value that is interpreted as the logical view name, with the model
|
||||
implicitly determined through command objects and `@ModelAttribute` annotated
|
||||
reference data accessor methods. The handler method may also programmatically enrich
|
||||
the model by declaring a `Model` argument (see above).
|
||||
|
|
@ -1431,22 +1431,25 @@ The following are the supported return types:
|
|||
* If the method is annotated with `@ResponseBody`, the return type is written to the
|
||||
response HTTP body. The return value will be converted to the declared method argument
|
||||
type using ``HttpMessageConverter``s. See <<mvc-ann-responsebody>>.
|
||||
* An `HttpEntity<?>` or `ResponseEntity<?>` object to provide access to the Servlet
|
||||
* `HttpEntity<?>` or `ResponseEntity<?>` object to provide access to the Servlet
|
||||
response HTTP headers and contents. The entity body will be converted to the response
|
||||
stream using ``HttpMessageConverter``s. See <<mvc-ann-httpentity>>.
|
||||
* An `HttpHeaders` object to return a response with no body.
|
||||
* A `Callable<?>` can be returned when the application wants to produce the return value
|
||||
asynchronously in a thread managed by Spring MVC.
|
||||
* A `DeferredResult<?>` can be returned when the application wants to produce the return
|
||||
value from a thread of its own choosing.
|
||||
* A `ListenableFuture<?>` or `CompletableFuture<?>`/`CompletionStage<?>` can be returned
|
||||
when the application wants to produce the value from a thread pool submission.
|
||||
* A `ResponseBodyEmitter` can be returned to write multiple objects to the response
|
||||
* `HttpHeaders` object to return a response with no body.
|
||||
* `Callable<?>` async computation in a Spring MVC managed thread.
|
||||
* `DeferredResult<?>` async result produced later from an application managed, or any thread.
|
||||
* `ListenableFuture<?>` as an alternative equivalent to using `DeferredResult`.
|
||||
* `CompletableFuture<?>` or `CompletionStage<?>` as an alternative equivalent to `DeferredResult`.
|
||||
* `ResponseBodyEmitter` can be returned to write multiple objects to the response
|
||||
asynchronously; also supported as the body within a `ResponseEntity`.
|
||||
* An `SseEmitter` can be returned to write Server-Sent Events to the response
|
||||
* `SseEmitter` can be returned to write Server-Sent Events to the response
|
||||
asynchronously; also supported as the body within a `ResponseEntity`.
|
||||
* A `StreamingResponseBody` can be returned to write to the response OutputStream
|
||||
* `StreamingResponseBody` can be returned to write to the response OutputStream
|
||||
asynchronously; also supported as the body within a `ResponseEntity`.
|
||||
* Reactive types from Reactor 3, RxJava 2, RxJava 1 or others registered through
|
||||
the configured `ReactiveAdapterRegistry` can be returned as an alternative
|
||||
equivalent to using `DeferredResult` for single-valued types, or
|
||||
`ResponseBodyEmitter` and `SseEmitter` for multi-valued reactive types where a streaming
|
||||
media type (e.g. "text/event-stream", "application/json+stream") is requested.
|
||||
* Any other return type is considered to be a single model attribute to be exposed to
|
||||
the view, using the attribute name specified through `@ModelAttribute` at the method
|
||||
level (or the default attribute name based on the return type class name). The model
|
||||
|
|
@ -2517,6 +2520,49 @@ Note that `StreamingResponseBody` can also be used as the body in a
|
|||
the response.
|
||||
|
||||
|
||||
[[mvc-ann-async-reactive-types]]
|
||||
==== Async Requests with Reactive Types
|
||||
|
||||
If using the reactive `WebClient` from `spring-webflux`, or another client, or
|
||||
a data store with reactive support, you can return reactive types directly from
|
||||
Spring MVC controller methods.
|
||||
|
||||
* If the return type has single-value stream semantics such as Reactor `Mono` or
|
||||
RxJava `Single` it is adapted and equivalent to using `DeferredResult`.
|
||||
* If the return type has multi-value stream semantics such as Reactor `Flux` or
|
||||
RxJava `Observable` / `Flowable` and if the media type indicates streaming, e.g.
|
||||
"application/stream+json" or "text/event-stream", it is adapted and equivalent to
|
||||
using `ResponseBodyEmitter` or `SseEmitter`. You can also return
|
||||
`Flux<ServerSentEvent>` or `Observable<ServerSentEvent>`.
|
||||
* If the return type has multi-value stream semantics but the media type does not
|
||||
imply streaming, e.g. "application/json", it is adapted and equivalent to using
|
||||
`DeferredResult<List<?>>`, e.g. JSON array.
|
||||
|
||||
Reactive libraries are detected and adapted to a Reactive Streams `Publisher`
|
||||
through Spring's pluggable `ReactiveAdapterRegistry` which by default supports
|
||||
Reactor 3, RxJava 2, and RxJava 1. Note that for RxJava 1 you will need to add
|
||||
https://github.com/ReactiveX/RxJavaReactiveStreams["io.reactivex:rxjava-reactive-streams"]
|
||||
to the classpath.
|
||||
|
||||
A common assumption with reactive libraries is not block the processing thread.
|
||||
The `WebClient` with Reactor Netty for example is based on event-loop style
|
||||
handling using a small, fixed number of threads and those must not be blocked
|
||||
when writing to the `ServletResponseOutputStream`. Reactive libraries have
|
||||
operators for that but Spring MVC automatically writes asynchronously so you
|
||||
don't need to use that. The underlying `TaskExecutor` for this can be configured
|
||||
through the MVC Java config and the MVC namespace as described in the following
|
||||
section.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
Unlike Spring MVC, Spring WebFlux is built on a non-blocking, reactive foundation
|
||||
and uses the Servlet 3.1 non-blocking I/O that's also based on event loop style
|
||||
processing and hence does not require a thread to absorb the effect of blocking.
|
||||
====
|
||||
|
||||
|
||||
|
||||
|
||||
[[mvc-ann-async-configuration]]
|
||||
==== Configuring Asynchronous Request Processing
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue