Refine @EnableWebFlux docs for functional endpoints

@EnableWebFlux bootstraps both annotated controllers and functional
endpoints, so we need to be more explicit about which parts of the
configuration apply to which.

Issue: SPR-16360
This commit is contained in:
Rossen Stoyanchev
2018-01-11 11:55:37 -05:00
parent 8f6d3feaa0
commit 72e3c43375
4 changed files with 69 additions and 53 deletions

View File

@@ -25,8 +25,11 @@ import java.lang.annotation.Target;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
/** /**
* Adding this annotation to an {@code @Configuration} class imports the Spring Web * Adding this annotation to an {@code @Configuration} class imports the Spring
* Reactive configuration from {@link WebFluxConfigurationSupport}, e.g.: * WebFlux configuration from {@link WebFluxConfigurationSupport} that enables
* use of annotated controllers and functional endpoints.
*
* <p>For example:
* *
* <pre class="code"> * <pre class="code">
* &#064;Configuration * &#064;Configuration
@@ -36,8 +39,8 @@ import org.springframework.context.annotation.Import;
* } * }
* </pre> * </pre>
* *
* <p>To customize the imported configuration implement * <p>To customize the imported configuration, implement
* {@link WebFluxConfigurer} and override individual methods as shown below: * {@link WebFluxConfigurer} and one or more of its methods:
* *
* <pre class="code"> * <pre class="code">
* &#064;Configuration * &#064;Configuration
@@ -46,33 +49,32 @@ import org.springframework.context.annotation.Import;
* public class MyConfiguration implements WebFluxConfigurer { * public class MyConfiguration implements WebFluxConfigurer {
* *
* &#064;Override * &#064;Override
* public void addFormatters(FormatterRegistry formatterRegistry) {
* formatterRegistry.addConverter(new MyConverter());
* }
*
* &#064;Override
* public void configureMessageWriters(List&lt;HttpMessageWriter&lt;?&gt&gt messageWriters) { * public void configureMessageWriters(List&lt;HttpMessageWriter&lt;?&gt&gt messageWriters) {
* messageWriters.add(new MyHttpMessageWriter()); * messageWriters.add(new MyHttpMessageWriter());
* } * }
*
* // ...
* } * }
* </pre> * </pre>
* *
* <p><strong>Note:</strong> only one {@code @Configuration} class may have the * <p>Only one {@code @Configuration} class should have the {@code @EnableWebFlux}
* {@code @EnableWebFlux} annotation to import the Spring WebFlux configuration. * annotation in order to import the Spring WebFlux configuration. There can
* There can however be multiple {@code @Configuration} classes implementing * however be multiple {@code @Configuration} classes that implement
* {@code WebFluxConfigurer} in order to customize the provided configuration. * {@code WebFluxConfigurer} that customize the provided configuration.
* *
* <p>If {@link WebFluxConfigurer} does not expose some more advanced setting * <p>If {@code WebFluxConfigurer} does not expose some setting that needs to be
* that needs to be configured consider removing the {@code @EnableWebFlux} * configured, consider switching to an advanced mode by removing the
* annotation and extending directly from {@link WebFluxConfigurationSupport} * {@code @EnableWebFlux} annotation and extending directly from
* or {@link DelegatingWebFluxConfiguration} if you still want to allow * {@link WebFluxConfigurationSupport} or {@link DelegatingWebFluxConfiguration} --
* {@link WebFluxConfigurer} instances to customize the configuration. * the latter allows detecting and delegating to one or more
* {@code WebFluxConfigurer} configuration classes.
* *
* @author Brian Clozel * @author Brian Clozel
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 5.0 * @since 5.0
* @see WebFluxConfigurer * @see WebFluxConfigurer
* @see WebFluxConfigurationSupport * @see WebFluxConfigurationSupport
* @see DelegatingWebFluxConfiguration
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) @Target(ElementType.TYPE)

View File

@@ -28,7 +28,7 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve
/** /**
* Defines callback methods to customize the configuration for WebFlux * Defines callback methods to customize the configuration for WebFlux
* applications enabled via {@code @EnableWebFlux}. * applications enabled via {@link EnableWebFlux @EnableWebFlux}.
* *
* <p>{@code @EnableWebFlux}-annotated configuration classes may implement * <p>{@code @EnableWebFlux}-annotated configuration classes may implement
* this interface to be called back and given a chance to customize the * this interface to be called back and given a chance to customize the
@@ -38,18 +38,25 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve
* @author Brian Clozel * @author Brian Clozel
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 5.0 * @since 5.0
* @see WebFluxConfigurationSupport
* @see DelegatingWebFluxConfiguration
*/ */
public interface WebFluxConfigurer { public interface WebFluxConfigurer {
/** /**
* Configure how the content type requested for the response is resolved. * Configure how the content type requested for the response is resolved
* when handling reqests with annotated controllers.
* @param builder for configuring the resolvers to use * @param builder for configuring the resolvers to use
*/ */
default void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { default void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
} }
/** /**
* Configure cross origin requests processing. * Configure "global" cross origin request processing.
* <p>The configured readers and writers will apply to all requests including
* annotated controllers and functional endpoints. Annotated controllers can
* further declare more fine-grained configuration via
* {@link org.springframework.web.bind.annotation.CrossOrigin @CrossOrigin}.
* @see CorsRegistry * @see CorsRegistry
*/ */
default void addCorsMappings(CorsRegistry registry) { default void addCorsMappings(CorsRegistry registry) {
@@ -57,8 +64,9 @@ public interface WebFluxConfigurer {
/** /**
* Configure path matching options. * Configure path matching options.
* * <p>The configured path matching options will be used for mapping to
* {@code HandlerMapping}s with path matching options. * annotated controllers and also
* {@link #addResourceHandlers(ResourceHandlerRegistry) static resources}.
* @param configurer the {@link PathMatchConfigurer} instance * @param configurer the {@link PathMatchConfigurer} instance
*/ */
default void configurePathMatching(PathMatchConfigurer configurer) { default void configurePathMatching(PathMatchConfigurer configurer) {
@@ -72,7 +80,7 @@ public interface WebFluxConfigurer {
} }
/** /**
* Configure resolvers for custom controller method arguments. * Configure resolvers for custom {@code @RequestMapping} method arguments.
* @param configurer to configurer to use * @param configurer to configurer to use
*/ */
default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
@@ -80,6 +88,8 @@ public interface WebFluxConfigurer {
/** /**
* Configure custom HTTP message readers and writers or override built-in ones. * Configure custom HTTP message readers and writers or override built-in ones.
* <p>The configured readers and writers will be used for both annotated
* controllers and functional endpoints.
* @param configurer the configurer to use * @param configurer the configurer to use
*/ */
default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
@@ -87,7 +97,7 @@ public interface WebFluxConfigurer {
/** /**
* Add custom {@link Converter}s and {@link Formatter}s for performing type * Add custom {@link Converter}s and {@link Formatter}s for performing type
* conversion and formatting of controller method arguments. * conversion and formatting of annotated controller method arguments.
*/ */
default void addFormatters(FormatterRegistry registry) { default void addFormatters(FormatterRegistry registry) {
} }
@@ -96,6 +106,8 @@ public interface WebFluxConfigurer {
* Provide a custom {@link Validator}. * Provide a custom {@link Validator}.
* <p>By default a validator for standard bean validation is created if * <p>By default a validator for standard bean validation is created if
* bean validation api is present on the classpath. * bean validation api is present on the classpath.
* <p>The configured validator is used for validating annotated controller
* method arguments.
*/ */
@Nullable @Nullable
default Validator getValidator() { default Validator getValidator() {
@@ -103,8 +115,9 @@ public interface WebFluxConfigurer {
} }
/** /**
* Provide a custom {@link MessageCodesResolver} to use for data binding instead * Provide a custom {@link MessageCodesResolver} to use for data binding in
* of the one created by default in {@link org.springframework.validation.DataBinder}. * annotated controller method arguments instead of the one created by
* default in {@link org.springframework.validation.DataBinder}.
*/ */
@Nullable @Nullable
default MessageCodesResolver getMessageCodesResolver() { default MessageCodesResolver getMessageCodesResolver() {
@@ -112,14 +125,11 @@ public interface WebFluxConfigurer {
} }
/** /**
* Configure view resolution for processing the return values of controller * Configure view resolution for rendering responses with a view and a model,
* methods that rely on resolving a * where the view is typically an HTML template but could also be based on
* {@link org.springframework.web.reactive.result.view.View} to render * an HTTP message writer (e.g. JSON, XML).
* the response with. By default all controller methods rely on view * <p>The configured view resolvers will be used for both annotated
* resolution unless annotated with {@code @ResponseBody} or explicitly * controllers and functional endpoints.
* return {@code ResponseEntity}. A view may be specified explicitly with
* a String return value or implicitly, e.g. {@code void} return value.
* @see ViewResolverRegistry
*/ */
default void configureViewResolvers(ViewResolverRegistry registry) { default void configureViewResolvers(ViewResolverRegistry registry) {
} }

View File

@@ -205,20 +205,21 @@ The returned `HttpHandler` can then be used with a number of servers adapters by
A more advanced option is to run with a A more advanced option is to run with a
<<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>>-based setup through the <<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>>-based setup through the
<<web-reactive.adoc#webflux-config>> which uses Spring configuration to declare the <<web-reactive.adoc#webflux-config>> which uses Spring configuration to declare the
components process requests. The WebFlux Java config declares the following components components quired to process requests. The WebFlux Java config declares the following
related to functional endpoints: infrastructure components to support functional endpoints:
* `RouterFunctionMapping` -- this detects one or more `RouterFunction<?>` beans in the * `RouterFunctionMapping` -- detects one or more `RouterFunction<?>` beans in the Spring
Spring configuration, combines them via `RouterFunction.andOther`, and routes requests to configuration, combines them via `RouterFunction.andOther`, and routes requests to the
the resulting, composed `RouterFunction`. resulting composed `RouterFunction`.
* `HandlerFunctionAdapter` -- simple adapter to invoke a `HandlerFunction` selected to * `HandlerFunctionAdapter` -- simple adapter that allows the `DispatcherHandler` to invoke
handle a request. a `HandlerFunction` that was mapped to a request.
* `ServerResponseResultHandler` -- invokes the `writeTo` method of the `ServerResponse` * `ServerResponseResultHandler` -- handles the result from the invocation of a
returned by the `HandlerFunction`. `HandlerFunction` by invoking the `writeTo` method of the `ServerResponse`.
The above allows functional endpoints to fit within the `DispatcherHandler` request The above components allow functional endpoints to fit within the `DispatcherHandler` request
processing lifecycle, and potentially to run side by side with annotated controllers, if processing lifecycle, and also potentially run side by side with annotated controllers, if
any are declared. This is also the mechanism used in the Spring Boot WebFlux starter. any are declared. It is also how functional endpoints are enabled the Spring Boot WebFlux
starter.
Below is example WebFlux Java config (see Below is example WebFlux Java config (see
<<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>> for how to run): <<web-reactive.adoc#webflux-dispatcher-handler,DispatcherHandler>> for how to run):

View File

@@ -1098,13 +1098,16 @@ include::webflux-functional.adoc[leveloffset=+1]
== WebFlux Java Config == WebFlux Java Config
[.small]#<<web.adoc#mvc-config,Same in Spring MVC>># [.small]#<<web.adoc#mvc-config,Same in Spring MVC>>#
The WebFlux Java config provides default configuration suitable for most applications along The WebFlux Java config declares components required to process requests with annotated
with a configuration API to customize it. For more advanced customizations, not available in controllers or functional endpoints, and it offers an API to customize the configuration.
the configuration API, see <<webflux-config-advanced-java>>. That means you do not need to understand the underlying beans created by the Java config
but, if you want to, it's very easy to see them in `WebFluxConfigurationSupport` or read more
what they are in <<webflux-special-bean-types>>.
For more advanced customizations, not available in the configuration API, it is also
possible to gain full control over the configuration through the
<<webflux-config-advanced-java>>.
You do not need to understand the underlying beans created by the Java config, but it's
easy to seem them in `WebFluxConfigurationSupport`, and if you want to learn more, see
<<webflux-special-bean-types>>.