Spring WebFlux applications are configured using Java configuration with the @EnableWebFlux annotation and the WebFluxConfigurer interface. This allows customization of HTTP message codecs, CORS mappings, path matching, view resolvers, resource handlers, API versioning, and more.
The @EnableWebFlux annotation imports Spring WebFlux configuration and enables the reactive web framework.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DelegatingWebFluxConfiguration.class)
public @interface EnableWebFlux { }Usage:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.EnableWebFlux;
@Configuration
@EnableWebFlux
public class WebConfig {
// Additional configuration beans
}Implement WebFluxConfigurer to customize various aspects of WebFlux configuration. All methods have default implementations, so you only need to override the ones relevant to your application.
public interface WebFluxConfigurer {
// Configure message readers and writers for request/response body conversion
default void configureHttpMessageCodecs(ServerCodecConfigurer configurer) { }
// Add custom formatters for data binding
default void addFormatters(FormatterRegistry registry) { }
// Provide a custom validator
default Validator getValidator() { return null; }
// Provide a custom MessageCodesResolver for data binding
default MessageCodesResolver getMessageCodesResolver() { return null; }
// Configure CORS (Cross-Origin Resource Sharing) mappings
default void addCorsMappings(CorsRegistry registry) { }
// Configure content type resolution strategy
default void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) { }
// Configure API versioning support
default void configureApiVersioning(ApiVersionConfigurer configurer) { }
// Configure path matching and path patterns
default void configurePathMatching(PathMatchConfigurer configurer) { }
// Configure custom argument resolvers for controller methods
default void configureArgumentResolvers(ArgumentResolverConfigurer configurer) { }
// Add ErrorResponse.Interceptor's for customizing RFC 9457 error responses
default void addErrorResponseInterceptors(List<ErrorResponse.Interceptor> interceptors) { }
// Configure view resolvers for rendering views
default void configureViewResolvers(ViewResolverRegistry registry) { }
// Add handlers for serving static resources
default void addResourceHandlers(ResourceHandlerRegistry registry) { }
// Configure blocking execution settings
default void configureBlockingExecution(BlockingExecutionConfigurer configurer) { }
// Provide a custom WebSocketService for WebSocket support configuration
default WebSocketService getWebSocketService() { return null; }
}Usage:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.config.EnableWebFlux;
import org.springframework.web.reactive.config.WebFluxConfigurer;
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://example.com")
.allowedMethods("GET", "POST");
}
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(false);
}
}Base classes that provide default WebFlux configuration.
public class WebFluxConfigurationSupport implements ApplicationContextAware {
// Defines default beans for WebFlux infrastructure
@Bean
public DispatcherHandler dispatcherHandler() { ... }
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping(
ServerCodecConfigurer serverCodecConfigurer,
RequestedContentTypeResolver webFluxContentTypeResolver) { ... }
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter(
ReactiveAdapterRegistry reactiveAdapterRegistry,
ServerCodecConfigurer serverCodecConfigurer,
FormattingConversionService webFluxConversionService,
Validator webFluxValidator) { ... }
@Bean
public FormattingConversionService webFluxConversionService() { ... }
@Bean
public Validator webFluxValidator() { ... }
@Bean
public ServerCodecConfigurer serverCodecConfigurer() { ... }
@Bean
public RequestedContentTypeResolver webFluxContentTypeResolver() { ... }
@Bean
public RouterFunctionMapping routerFunctionMapping(ServerCodecConfigurer serverCodecConfigurer) { ... }
@Bean
public HandlerFunctionAdapter handlerFunctionAdapter() { ... }
@Bean
public ServerResponseResultHandler serverResponseResultHandler(ServerCodecConfigurer serverCodecConfigurer) { ... }
@Bean
public ResponseEntityResultHandler responseEntityResultHandler(
ReactiveAdapterRegistry reactiveAdapterRegistry,
ServerCodecConfigurer serverCodecConfigurer,
RequestedContentTypeResolver webFluxContentTypeResolver) { ... }
@Bean
public ResponseBodyResultHandler responseBodyResultHandler(
ReactiveAdapterRegistry reactiveAdapterRegistry,
ServerCodecConfigurer serverCodecConfigurer,
RequestedContentTypeResolver webFluxContentTypeResolver) { ... }
@Bean
public ViewResolutionResultHandler viewResolutionResultHandler(
ReactiveAdapterRegistry reactiveAdapterRegistry,
RequestedContentTypeResolver webFluxContentTypeResolver) { ... }
@Bean
public WebFluxResponseStatusExceptionHandler responseStatusExceptionHandler() { ... }
}public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
// Automatically detects and delegates to WebFluxConfigurer beans
// in the application context
}public class WebFluxConfigurerComposite implements WebFluxConfigurer {
public void addWebFluxConfigurers(List<WebFluxConfigurer> configurers) { ... }
// Delegates all WebFluxConfigurer methods to the added configurers
}Configure path pattern parsing and matching behavior.
public class PathMatchConfigurer {
// Configure whether to use trailing slash matching
public PathMatchConfigurer setUseTrailingSlashMatch(Boolean trailingSlashMatch) { ... }
// Set whether to use case-sensitive pattern matching
public PathMatchConfigurer setUseCaseSensitiveMatch(Boolean caseSensitiveMatch) { ... }
// Configure the PathPatternParser
public PathMatchConfigurer setPathPatternParser(PathPatternParser patternParser) { ... }
public Boolean isUseTrailingSlashMatch() { ... }
public Boolean isUseCaseSensitiveMatch() { ... }
public PathPatternParser getPathPatternParser() { ... }
}Usage:
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer
.setUseTrailingSlashMatch(false)
.setUseCaseSensitiveMatch(true);
}Configure Cross-Origin Resource Sharing (CORS) mappings for specific path patterns.
public class CorsRegistry {
// Add a CORS mapping for the specified path pattern
public CorsRegistration addMapping(String pathPattern) { ... }
}public class CorsRegistration {
// Allowed origins for cross-origin requests
public CorsRegistration allowedOrigins(String... origins) { ... }
public CorsRegistration allowedOriginPatterns(String... patterns) { ... }
// Allowed HTTP methods
public CorsRegistration allowedMethods(String... methods) { ... }
// Allowed request headers
public CorsRegistration allowedHeaders(String... headers) { ... }
// Headers exposed to the client
public CorsRegistration exposedHeaders(String... headers) { ... }
// Whether credentials are allowed
public CorsRegistration allowCredentials(Boolean allowCredentials) { ... }
// Max age of preflight cache in seconds
public CorsRegistration maxAge(long maxAge) { ... }
}Usage:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("https://example.com", "https://app.example.com")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}Configure handlers for serving static resources (CSS, JavaScript, images, etc.).
public class ResourceHandlerRegistry {
// Add a resource handler for the specified path patterns
public ResourceHandlerRegistration addResourceHandler(String... pathPatterns) { ... }
// Set the order for resource handling
public ResourceHandlerRegistry setOrder(int order) { ... }
public int getOrder() { ... }
}public class ResourceHandlerRegistration {
// Add resource locations (file system or classpath)
public ResourceHandlerRegistration addResourceLocations(String... locations) { ... }
// Configure cache control for resources
public ResourceHandlerRegistration setCacheControl(CacheControl cacheControl) { ... }
// Set whether to use last modified timestamps
public ResourceHandlerRegistration setUseLastModified(boolean useLastModified) { ... }
// Set whether to optimize resource locations
public ResourceHandlerRegistration setOptimizeLocations(boolean optimizeLocations) { ... }
// Configure a chain of resource resolvers and transformers
public ResourceChainRegistration resourceChain(boolean cacheResources) { ... }
public ResourceChainRegistration resourceChain(boolean cacheResources, Cache cache) { ... }
}public class ResourceChainRegistration {
// Add custom resource resolver
public ResourceChainRegistration addResolver(ResourceResolver resolver) { ... }
// Add custom resource transformer
public ResourceChainRegistration addTransformer(ResourceTransformer transformer) { ... }
// Enable HTML5 app cache manifest transformation
public ResourceChainRegistration htmlApplicationCache() { ... }
// Enable versioning strategy for resources
public VersionResourceResolver versionResolver() { ... }
}Usage:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
.resourceChain(true)
.addResolver(new VersionResourceResolver()
.addContentVersionStrategy("/**"));
}Configure view resolvers for rendering views with template engines.
public class ViewResolverRegistry {
// Set the order for view resolution
public void order(int order) { ... }
// Register a FreeMarker view resolver
public UrlBasedViewResolverRegistration freeMarker() { ... }
// Register a script template view resolver
public UrlBasedViewResolverRegistration scriptTemplate() { ... }
// Register a custom view resolver
public void viewResolver(ViewResolver viewResolver) { ... }
// Add default views
public void defaultViews(View... defaultViews) { ... }
}public class UrlBasedViewResolverRegistration {
// Set view names that can be handled
public UrlBasedViewResolverRegistration viewNames(String... viewNames) { ... }
// Set view class
public UrlBasedViewResolverRegistration viewClass(Class<?> viewClass) { ... }
// Set prefix for view names
public UrlBasedViewResolverRegistration prefix(String prefix) { ... }
// Set suffix for view names
public UrlBasedViewResolverRegistration suffix(String suffix) { ... }
// Set cache for resolved views
public UrlBasedViewResolverRegistration cache(boolean cache) { ... }
// Set cache limit
public UrlBasedViewResolverRegistration cacheLimit(int cacheLimit) { ... }
}Usage:
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker()
.prefix("/templates/")
.suffix(".ftl")
.cache(true);
}Configure settings for blocking operations in WebFlux applications.
public class BlockingExecutionConfigurer {
// Set the scheduler to use for blocking operations
public BlockingExecutionConfigurer setExecutor(Scheduler scheduler) { ... }
public Scheduler getExecutor() { ... }
}Usage:
@Override
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
configurer.setExecutor(Schedulers.boundedElastic());
}Configure API versioning support including version resolution and deprecation handling.
public class ApiVersionConfigurer {
// Add an API version resolver
public ApiVersionConfigurer addVersionResolver(ApiVersionResolver resolver) { ... }
// Set the API version strategy
public ApiVersionConfigurer setVersionStrategy(ApiVersionStrategy strategy) { ... }
// Set the deprecation handler
public ApiVersionConfigurer setDeprecationHandler(ApiVersionDeprecationHandler handler) { ... }
}Usage:
@Override
public void configureApiVersioning(ApiVersionConfigurer configurer) {
configurer
.addVersionResolver(new HeaderApiVersionResolver("API-Version"))
.setVersionStrategy(new DefaultApiVersionStrategy())
.setDeprecationHandler(new StandardApiVersionDeprecationHandler());
}Configure custom argument resolvers for controller method parameters.
public class ArgumentResolverConfigurer {
// Add custom argument resolvers before default resolvers
public ArgumentResolverConfigurer addCustomResolver(HandlerMethodArgumentResolver... resolvers) { ... }
}Usage:
@Override
public void addArgumentResolvers(ArgumentResolverConfigurer configurer) {
configurer.addCustomResolver(new MyCustomArgumentResolver());
}public interface HandlerMapping {
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";
Mono<Object> getHandler(ServerWebExchange exchange);
}public interface HandlerAdapter {
boolean supports(Object handler);
Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler);
}public interface HandlerResultHandler {
boolean supports(HandlerResult result);
Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result);
}