WebFlux配置
启用WebFlux配置
您可以在Java配置中使用@EnableWebFlux
注解,如下例所示:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig {
}
@Configuration
@EnableWebFlux
class WebConfig
上面的例子注册了一些Spring WebFlux 基础设施bean,并适应了类路径上可用的依赖项,用于JSON、XML等。
WebFlux配置API
在您的Java配置中,您可以实现WebFluxConfigurer
接口,如下例所示:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
// 实现配置方法...
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
// 实现配置方法...
}
转换、格式化
默认情况下,安装了各种数字和日期类型的格式化程序,以及通过在字段上使用@NumberFormat
和@DateTimeFormat
进行自定义支持。
要在Java配置中注册自定义格式化程序和转换器,请使用以下内容:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
// ...
}
}
默认情况下,Spring WebFlux在解析和格式化日期值时考虑请求的区域设置。这适用于表单,其中日期表示为带有"input"表单字段的字符串。但是,对于"date"和"time"表单字段,浏览器使用HTML规范中定义的固定格式。对于这种情况,可以自定义日期和时间格式化如下:
-
Java
-
Kotlin
@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)
}
}
查看FormatterRegistrar SPI和FormattingConversionServiceFactoryBean ,了解何时使用FormatterRegistrar 实现的更多信息。 |
验证
默认情况下,如果类路径上存在Bean验证(例如,Hibernate Validator),则将LocalValidatorFactoryBean
注册为全局验证器,以便在@Controller
方法参数上使用@Valid
和@Validated
。
在您的Java配置中,您可以自定义全局Validator
实例,如下例所示:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public Validator getValidator() {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun getValidator(): Validator {
// ...
}
}
Validator
实现,如下例所示:
-
Java
-
Kotlin
@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 ,请创建一个bean,并使用@Primary 标记它,以避免与在MVC配置中声明的冲突。 |
内容类型解析器
@Controller实例。默认情况下,仅检查
Accept
标头,但您也可以启用基于查询参数的策略。
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) {
// ...
}
}
HTTP消息编解码器
-
Java
-
Kotlin
@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
提供一组默认的读取器和写入器。您可以使用它来添加更多的读取器和写入器,自定义默认的读取器和写入器,或完全替换默认的读取器和写入器。
Jackson2ObjectMapperBuilder
,它使用以下属性自定义Jackson的默认属性:
-
jackson-datatype-joda
:支持Joda-Time类型。 -
jackson-datatype-jsr310
:支持Java 8日期和时间API类型。 -
jackson-datatype-jdk8
:支持其他Java 8类型,如Optional
。 -
jackson-module-kotlin
:支持Kotlin类和数据类。
视图解析器
以下示例显示了如何配置视图解析:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// ...
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
// ...
}
}
ViewResolverRegistry
提供了与Spring Framework集成的视图技术的快捷方式。以下示例使用了FreeMarker(还需要配置底层的FreeMarker视图技术):
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
}
// 配置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()
}
// 配置FreeMarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates")
}
}
您还可以插入任何ViewResolver
实现,如下例所示:
-
Java
-
Kotlin
@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)
}
}
为了支持内容协商并通过视图解析呈现其他格式(除了HTML),您可以基于HttpMessageWriterView
实现配置一个或多个默认视图,该实现接受来自spring-web
的任何可用Codecs。以下示例显示了如何实现:
-
Java
-
Kotlin
@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))
}
// ...
}
有关与Spring WebFlux集成的视图技术的更多信息,请参阅视图技术。
静态资源
此选项提供了一种方便的方式,从基于Resource
的位置列表中提供静态资源。
在下一个示例中,对于以/resources
开头的请求,相对路径用于查找和提供相对于类路径上的/static
的静态资源。资源将以一年后的到期日提供,以确保最大限度地利用浏览器缓存,并减少浏览器发出的HTTP请求。还会评估Last-Modified
标头,如果存在,则返回304
状态码。以下清单显示了示例:
-
Java
-
Kotlin
@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))
}
}
另请参阅静态资源的HTTP缓存支持。
资源处理程序还支持一系列ResourceResolver
实现和ResourceTransformer
实现,可用于创建用于处理优化资源的工具链。
您可以使用VersionResourceResolver
根据从内容计算的MD5哈希、固定应用程序版本或其他信息生成带版本的资源URL。对于一些特殊情况(例如与模块加载器一起使用的JavaScript资源),ContentVersionStrategy
(MD5哈希)是一个不错的选择。
以下示例展示了如何在Java配置中使用VersionResourceResolver
:
-
Java
-
Kotlin
@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("/**"))
}
}
您可以使用ResourceUrlProvider
重写URL并应用完整的解析器和转换器链(例如,插入版本)。WebFlux配置提供了一个ResourceUrlProvider
,因此可以将其注入到其他位置。
与Spring MVC不同,在WebFlux中目前无法透明地重写静态资源URL,因为没有视图技术可以利用非阻塞的解析器和转换器链。当仅提供本地资源时,解决方法是直接使用ResourceUrlProvider
(例如,通过自定义元素)并阻塞。
请注意,当同时使用EncodedResourceResolver
(例如,Gzip、Brotli编码)和VersionedResourceResolver
时,它们必须按顺序注册,以确保始终可靠地基于未编码文件计算基于内容的版本。
对于WebJars,建议使用类似/webjars/jquery/1.2.0/jquery.min.js
的带版本的URL。相关的资源位置在Spring Boot中已经配置好(或者可以通过ResourceHandlerRegistry
手动配置),不需要添加org.webjars:webjars-locator-core
依赖项。
支持无版本的URL,例如/webjars/jquery/jquery.min.js
,通过WebJarsResourceResolver
支持,当类路径上存在org.webjars:webjars-locator-core
库时会自动注册,但这会导致类路径扫描,可能会减慢应用程序启动速度。解析器可以重写URL以包含jar的版本,并且还可以匹配不带版本的传入URL,例如,从/webjars/jquery/jquery.min.js
到/webjars/jquery/1.2.0/jquery.min.js
。
基于ResourceHandlerRegistry 的Java配置提供了进一步的选项,用于精细控制,例如最后修改的行为和优化的资源解析。 |
路径匹配
您可以自定义与路径匹配相关的选项。有关各个选项的详细信息,请参阅PathMatchConfigurer
的javadoc。以下示例显示了如何使用PathMatchConfigurer
:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Override
fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}
}
Spring WebFlux依赖于称为 与Spring MVC不同,Spring WebFlux也不支持后缀模式匹配,我们也建议不再依赖于它。 |
阻塞执行
WebFlux Java配置允许您自定义WebFlux中的阻塞执行。
您可以通过提供AsyncTaskExecutor
(例如VirtualThreadTaskExecutor
)来在单独的线程上调用阻塞控制器方法,如下所示:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
AsyncTaskExecutor executor = ...
configurer.setExecutor(executor);
}
}
@Configuration
@EnableWebFlux
class WebConfig : WebFluxConfigurer {
@Override
fun configureBlockingExecution(configurer: BlockingExecutionConfigurer) {
val executor = ...
configurer.setExecutor(executor)
}
}
默认情况下,控制器方法的返回类型未被配置的ReactiveAdapterRegistry
识别时被视为阻塞的,但您可以通过BlockingExecutionConfigurer
设置自定义控制器方法谓词。
WebSocket服务
WebFlux Java配置声明了一个WebSocketHandlerAdapter
bean,提供对WebSocket处理程序的调用支持。这意味着处理WebSocket握手请求的剩下工作就是通过SimpleUrlHandlerMapping
将WebSocketHandler
映射到URL。
在某些情况下,可能需要使用提供的WebSocketService
服务创建WebSocketHandlerAdapter
bean,该服务允许配置WebSocket服务器属性。例如:
-
Java
-
Kotlin
@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)
}
}
高级配置模式
@EnableWebFlux
导入DelegatingWebFluxConfiguration
,它:
-
为WebFlux应用程序提供默认的Spring配置
-
检测并委托给
WebFluxConfigurer
实现以自定义该配置。
对于高级模式,您可以移除@EnableWebFlux
,直接从DelegatingWebFluxConfiguration
扩展,而不是实现WebFluxConfigurer
,如下例所示:
-
Java
-
Kotlin
@Configuration
public class WebConfig extends DelegatingWebFluxConfiguration {
// ...
}
@Configuration
class WebConfig : DelegatingWebFluxConfiguration {
// ...
}
您可以保留WebConfig
中的现有方法,但现在还可以覆盖基类中的bean声明,并仍然具有任意数量的其他WebMvcConfigurer
实现在类路径中。