The WebFlux Java configuration declares the components needed to process requests using annotated controllers or functional endpoints and provides an API for setting up the configuration. This means that you don't need to understand the underlying beans created by Java configuration.
If you need advanced settings that are not available in the configuration API, you can gain full control over the configuration using the advanced configuration mode.
Enabling WebFlux Configuration
You can use the @EnableWebFlux
annotation in a Java configuration as shown in the following example:
@Configuration
@EnableWebFlux
public class WebConfig {
}
@Configuration
@EnableWebFlux
class WebConfig
In the previous example, a number of Spring WebFlux infrastructure beans are registered and adapted to the dependencies available in the classpath - for JSON, XML and others formats.
WebFlux Configuration API
In your Java configuration, you can implement the WebFluxConfigurer
interface, as shown in the
following example:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
// Implement configuration methods...
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
// Implement configuration methods...
}
Conversion, formatting
By default, formatters are installed for various types of numbers and dates, along with tools to support
customization via @NumberFormat
and @DateTimeFormat
for fields.
To register custom formatters and converters in the Java configuration, use the following:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
// ...
}
}
By default, Spring WebFlux takes into account the request's locale when parsing and formatting date values. This is true for forms where dates are represented as strings with "input" form fields. However, for the "date" and "time" form fields, browsers use a fixed format defined in the HTML specification. For such cases, date and time formatting can be configured as follows:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(registry);
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
val registrar = DateTimeFormatterRegistrar()
registrar.setUseIsoFormat(true)
registrar.registerFormatters(registry)
}
}
Validation
Default if in classpath a Bean Validation is present (e.g. Hibernate Validator), a
LocalValidatorFactoryBean
is registered as a global validator for use with the @Valid
annotation and the
Validated
property on method arguments.
In Java configuration, you can configure a global Validator
instance, as shown in the following
example:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public Validator getValidator() {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun getValidator(): Validator {
// ...
}
}
Note that it is also possible to register Validator
implementations locally, as shown in the
following example:
@Controller
public class MyController {
@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new FooValidator());
}
}
@Controller
class MyController {
@InitBinder
protected fun initBinder(binder: WebDataBinder) {
binder.addValidators(FooValidator())
}
}
LocalValidatorFactoryBean
was
injected somewhere, create a bean and mark it with the @Primary
annotation to avoid conflicting
with what was declared in the MVC configuration.
Resolvers content types
You can configure how Spring WebFlux determines the requested media types for @Controller
instances
from a request. By default, only the Accept
header is checked, but you can also enable a strategy
based on request parameters.
The following example shows how to configure the permission of the requested content type:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) {
// ...
}
}
HTTP message codecs
The following example shows how to configure the reading and writing of the request and response body:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().maxInMemorySize(512 * 1024);
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
// ...
}
}
ServerCodecConfigurer
provides a default set of readers and writers. You can use it to add
additional readers and writers, customize the default ones, or replace the default ones entirely.
For Jackson JSON and XML, consider using Jackson2ObjectMapperBuilder
, which configures the Jackson library properties
according to default to the following:
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
– disabled.MapperFeature.DEFAULT_VIEW_INCLUSION
- disabled.
The following known modules are also automatically registered if they are found in the classpath:
jackson-datatype-joda
: Support for Joda-Time types.jackson-datatype-jsr310
: Support for Java 8 date and time API types.jackson-datatype-jdk8
: Support for other Java 8 types such asOptional
.jackson-module-kotlin
: Support for Kotlin classes and data classes.
View Recognizers
The following example shows how to configure view recognition:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
// ...
}
}
ViewResolverRegistry
contains abbreviations for the presentation technologies that the Spring
Framework integrates with. The following example uses FreeMarker (which also requires customization of the
underlying FreeMarker presentation technology):
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// Configure FreeMarker...
@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("classpath:/templates");
return configurer;
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Configure FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates")
}
}
You can also connect any ViewResolver
implementation, as shown in the following example:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ViewResolver resolver = ... ;
registry.viewResolver(resolver);
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
val resolver: ViewResolver = ...
registry.viewResolver(resolver
}
}
To provide support for content negotiation and rendering of other formats through view resolution (other than
HTML), you can configure one or more default views based on the HttpMessageWriterView
, which accepts
any of the available codecs from spring-web
. The following example shows
how to do this:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
registry.defaultViews(new HttpMessageWriterView(encoder));
}
// ...
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
val encoder = Jackson2JsonEncoder()
registry.defaultViews(HttpMessageWriterView(encoder))
}
// ...
}
Static Resources
This option provides a convenient way to handle static resources from a list of locations based on Resource
.
In the following example, if the request starts with /resources
, the relative path is used to find
and process static resources relative to /static
in the classpath. Resources are processed with an
expiration date of one year to ensure maximum use of the browser cache and reduce the number of HTTP requests
made by the browser. The Last-Modified
header is also evaluated and, if present, a 304
status code is returned. The following listing shows an example:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public", "classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public", "classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
}
}
The resource handler also supports implementation chaining ResourceResolver
and implementations ResourceTransformer
, which can be used to create a toolkit for working
with optimized resources.
You can use VersionResourceResolver
for versioned resource URLs based on an MD5 hash derived from
the content, immutable application version, or other information. ContentVersionStrategy
(MD5 hash)
is a thoughtful choice, but with some notable exceptions (such as JavaScript resources used with the module
loader).
The following example shows how to use VersionResourceResolver
in Java configuration:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public/")
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public/")
.resourceChain(true)
.addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
}
}
You can use ResourceUrlProvider
to rewrite URLs and applying the full chain of resolvers and
resolvers (for example, to insert versions). WebFlux configuration provides a ResourceUrlProvider
that can be injected into other beans.
Unlike Spring MVC, WebFlux currently does not have the ability to transparently rewrite static resource URLs
because there are no presentation technologies which could use a non-blocking chain of resolvers and resolvers.
When processing only local resources, a workaround is to use ResourceUrlProvider
directly (for
example, through a custom element) and block.
Note that when used as EncodedResourceResolver
(e.g. Gzip, Brotli) and
VersionedResourceResolver
,
they must be registered in an order that will reliably calculate versions based on the contents of the unencoded
file.
WebJars are also supported using the WebJarsResourceResolver
,
which is automatically registered when the org.webjars:webjars-locator-core
library is present in
classpath. The resolver can rewrite URLs to include the jar version, as well as match incoming URLs without
versions - for example, from /jquery/jquery.min.js
to /jquery/1.2.0/jquery.min.js
.
ResourceHandlerRegistry
provides
additional capabilities for fine-grained control, such as last-change logic and optimized resource resolution.
Path Mapping
You can configure settings related to path mapping. For more information about individual parameters, see the
javadoc at PathMatchConfigurer
. The following example shows how to use
PathMatchConfigurer
:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseCaseSensitiveMatch(true)
.setUseTrailingSlashMatch(false)
.addPathPrefix("/api",
HandlerTypePredicate.forAnnotation(RestController.class));
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Override
fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer
.setUseCaseSensitiveMatch(true)
.setUseTrailingSlashMatch(false)
.addPathPrefix("/api",
HandlerTypePredicate.forAnnotation(RestController::class.java))
}
}
Spring WebFlux uses a parsed path representation a request called RequestPath
to access the decoded values of path segments, with the semicolon-delimited contents removed (that is, path
variables or matrix variables). This means that, unlike Spring MVC, there is no need to specify whether to decode
the request path or remove semicolon-separated content to match paths.
Spring WebFlux also does not support suffix pattern matching, unlike Spring MVC, where we also recommend not to use it.
WebSocketService
In the WebFlux Java configuration, the WebSocketHandlerAdapter
bean is declared , which provides support for calling WebSocket handlers. This means that all that is left to handle
a WebSocket handshake request is to map the WebSocketHandler
to a URL via
SimpleUrlHandlerMapping
.
In some cases, it may you will need to create a WebSocketHandlerAdapter
bean with the provided WebSocketService
service, which allows you to configure the properties of the
server working with the WebSocket protocol. For example:
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public WebSocketService getWebSocketService() {
TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
strategy.setMaxSessionIdleTimeout(0L);
return new HandshakeWebSocketService(strategy);
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Override
fun webSocketService(): WebSocketService {
val strategy = TomcatRequestUpgradeStrategy().apply {
setMaxSessionIdleTimeout(0L)
}
return HandshakeWebSocketService(strategy)
}
}
Advanced configuration mode
@EnableWebFlux
imports
DelegatingWebFluxConfiguration
, which:
Pass the default Spring configuration for WebFlux applications
discovers and delegates authority to the
WebFluxConfigurer
implementation to set up this configuration.
In advanced mode, you can remove the @EnableWebFlux
annotation code> and extend directly from
DelegatingWebFluxConfiguration
instead of implementing WebFluxConfigurer
as shown in the
following example:
@Configuration
public class WebConfig extends DelegatingWebFluxConfiguration {
// ...
}
@Configuration
class WebConfig : DelegatingWebFluxConfiguration {
// ...
}
It is possible to save existing methods in WebConfig
, but now it will also be possible to
override bean declarations from base class, and still be able to have any number of other
WebMvcConfigurer
implementations in the classpath.
HTTP/2
HTTP/2 is supported in Reactor Netty, Tomcat, Jetty and Undertow. However, there are some caveats associated with the server configuration. More information can be found at wiki page over HTTP/2.
GO TO FULL VERSION