WebFlux Config
WebFlux Java 配置声明了处理带注释控制器或功能端点请求所需的组件,并提供了一个 API 来自定义配置。这意味着您无需了解 Java 配置创建的底层 Bean。但是,如果您想了解它们,可以在 WebFluxConfigurationSupport
中查看,或者在 Special Bean Types 中阅读更多有关它们的信息。
The WebFlux Java configuration declares the components that are required to process
requests with annotated controllers or functional endpoints, and it offers an API to
customize the configuration. That means you do not need to understand the underlying
beans created by the Java configuration. However, if you want to understand them,
you can see them in WebFluxConfigurationSupport
or read more about what they are
in Special Bean Types.
对于配置 API 中不可用的更高级的自定义,您可以通过 Advanced Configuration Mode 完全控制配置。
For more advanced customizations, not available in the configuration API, you can gain full control over the configuration through the Advanced Configuration Mode.
Enabling WebFlux Config
你可以在你的 Java 配置中使用 @EnableWebFlux
注释,如下例所示:
You can use the @EnableWebFlux
annotation in your Java config, as the following example shows:
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig {
}
@Configuration
@EnableWebFlux
class WebConfig
在使用 Spring Boot 时,您可能希望使用类型为 |
When using Spring Boot, you may want to use |
前面的示例注册了许多 Spring WebFlux infrastructure beans,并适应 classpath 上可用的依赖项——JSON、XML 等。
The preceding example registers a number of Spring WebFlux infrastructure beans and adapts to dependencies available on the classpath — for JSON, XML, and others.
WebFlux config API
在 Java 配置中,您可以实现 WebFluxConfigurer
接口,如下所示:
In your Java configuration, you can implement the WebFluxConfigurer
interface,
as the following example shows:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
// Implement configuration methods...
}
@Configuration
class WebConfig : WebFluxConfigurer {
// Implement configuration methods...
}
Conversion, formatting
在默认情况下,也会安装各种数字和日期类型的格式化程序,以及通过字段中的 @NumberFormat
和 @DateTimeFormat
自定义的支持。
By default, formatters for various number and date types are installed, along with support
for customization via @NumberFormat
and @DateTimeFormat
on fields.
要在 Java 配置中注册自定义格式化程序和转换器,请使用以下信息:
To register custom formatters and converters in Java config, use the following:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
// ...
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
// ...
}
}
默认情况下,Spring WebFlux 在解析和格式化日期值时会考虑请求区域设置。这适用于日期表示为带有“input”表单字段的字符串的表单。但是,对于“date”和“time”表单字段,浏览器使用 HTML 规范中定义的固定格式。对于此类情况,日期和时间格式化可以按照如下方式自定义:
By default Spring WebFlux considers the request Locale when parsing and formatting date values. This works for forms where dates are represented as Strings with "input" form fields. For "date" and "time" form fields, however, browsers use a fixed format defined in the HTML spec. For such cases date and time formatting can be customized as follows:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
registrar.setUseIsoFormat(true);
registrar.registerFormatters(registry);
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun addFormatters(registry: FormatterRegistry) {
val registrar = DateTimeFormatterRegistrar()
registrar.setUseIsoFormat(true)
registrar.registerFormatters(registry)
}
}
有关何时使用 |
See |
Validation
默认情况下,如果 Bean Validation 存在于 classpath 中(例如,Hibernate Validator),则 LocalValidatorFactoryBean
将注册为一个全局 validator,以用于 @Valid
和 @Validated
中的 @Controller
方法参数。
By default, if Bean Validation is present
on the classpath (for example, the Hibernate Validator), the LocalValidatorFactoryBean
is registered as a global validator for use with @Valid
and
@Validated
on @Controller
method arguments.
在 Java 配置中,您可以自定义全局 Validator
实例,如下所示:
In your Java configuration, you can customize the global Validator
instance,
as the following example shows:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public Validator getValidator() {
// ...
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun getValidator(): Validator {
// ...
}
}
请注意,您还可以按照如下所示局部注册 Validator
实现:
Note that you can also register Validator
implementations locally,
as the following example shows:
-
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())
}
}
如果您需要在某处注入 |
If you need to have a |
Content Type Resolvers
您可以配置 Spring WebFlux 如何从请求中确定 @Controller
实例的请求媒体类型。默认情况下,仅检查 Accept
标头,但您还可以启用基于查询参数的策略。
You can configure how Spring WebFlux determines the requested media types for
@Controller
instances from the request. By default, only the Accept
header is checked,
but you can also enable a query parameter-based strategy.
以下示例显示如何自定义请求内容类型解析:
The following example shows how to customize the requested content type resolution:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
// ...
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) {
// ...
}
}
HTTP message codecs
以下示例显示如何自定义请求和响应正文的读取和写入方式:
The following example shows how to customize how the request and response body are read and written:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().maxInMemorySize(512 * 1024);
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
configurer.defaultCodecs().maxInMemorySize(512 * 1024)
}
}
ServerCodecConfigurer
提供了一组默认读取器和写入器。您可以使用它来添加更多读取器和写入器,自定义默认读取器和写入器,或完全替换默认读取器和写入器。
ServerCodecConfigurer
provides a set of default readers and writers. You can use it to add
more readers and writers, customize the default ones, or replace the default ones completely.
对于 Jackson JSON 和 XML,考虑使用 Jackson2ObjectMapperBuilder
,它使用以下配置定制 Jackson 的默认属性:
For Jackson JSON and XML, consider using
Jackson2ObjectMapperBuilder
,
which customizes Jackson’s default properties with the following ones:
-
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
is disabled. -
MapperFeature.DEFAULT_VIEW_INCLUSION
is disabled.
如果在类路径中检测到以下著名的模块,它还将自动注册这些模块:
It also automatically registers the following well-known modules if they are detected on 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 Resolvers
以下示例显示如何配置视图解析:
The following example shows how to configure view resolution:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
// ...
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
// ...
}
}
`ViewResolverRegistry`提供了 Spring Framework 集成的视图技术快捷方式。以下示例使用 FreeMarker(还需要配置基础的 FreeMarker 视图技术):
The ViewResolverRegistry
has shortcuts for view technologies with which the Spring Framework
integrates. The following example uses FreeMarker (which also requires configuring the
underlying FreeMarker view technology):
-
Java
-
Kotlin
@Configuration
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
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
}
// Configure Freemarker...
@Bean
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
setTemplateLoaderPath("classpath:/templates")
}
}
还可以插入任何 ViewResolver
实现,如下面的示例所示:
You can also plug in any ViewResolver
implementation, as the following example shows:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ViewResolver resolver = ... ;
registry.viewResolver(resolver);
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
val resolver: ViewResolver = ...
registry.viewResolver(resolver
}
}
要支持 Content Negotiation 并通过视图解析(除了 HTML)呈现其他格式,您可以根据 HttpMessageWriterView
实现配置一个或多个默认视图,该实现接受来自 spring-web
的任何可用的 Codecs。以下示例展示了如何执行此操作:
To support Content Negotiation and rendering other formats
through view resolution (besides HTML), you can configure one or more default views based
on the HttpMessageWriterView
implementation, which accepts any of the available
Codecs from spring-web
. The following example shows how to do so:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.freeMarker();
Jackson2JsonEncoder encoder = new Jackson2JsonEncoder();
registry.defaultViews(new HttpMessageWriterView(encoder));
}
// ...
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureViewResolvers(registry: ViewResolverRegistry) {
registry.freeMarker()
val encoder = Jackson2JsonEncoder()
registry.defaultViews(HttpMessageWriterView(encoder))
}
// ...
}
请参阅 View Technologies 以详细了解与 Spring WebFlux 集成的视图技术。
See View Technologies for more on the view technologies that are integrated with Spring WebFlux.
Static Resources
此选项提供了一种方便的方法来基于一组https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/Resource.html[Resource
] 位置提供静态资源。
This option provides a convenient way to serve static resources from a list of
Resource
-based locations.
在下一个示例中,给定从 /resources
开始的请求,将使用相对路径在类路径上的 /static
相对于查找并提供静态资源。提供资源时将会有一年的未来到期时间,以确保最大程度地利用浏览器缓存并减少浏览器发出的 HTTP 请求。还将计算 Last-Modified
标头,如果存在,则返回 304
状态代码。以下列表显示了该示例:
In the next example, given a request that starts with /resources
, the relative path is
used to find and serve static resources relative to /static
on the classpath. Resources
are served with a one-year future expiration to ensure maximum use of the browser cache
and a reduction in 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
the example:
-
Java
-
Kotlin
@Configuration
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
class WebConfig : WebFluxConfigurer {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public", "classpath:/static/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
}
}
资源处理程序还支持“https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/resource/ResourceResolver.html[ResourceResolver
]”实现和“https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/resource/ResourceTransformer.html[ResourceTransformer
]”实现的链,可用来创建工具链,以便处理经过优化的资源。
The resource handler also supports a chain of
ResourceResolver
implementations and
ResourceTransformer
implementations,
which can be used to create a toolchain for working with optimized resources.
可以将 VersionResourceResolver
用于基于内容 MD5 哈希、固定应用程序版本或其他信息的版本化资源 URL。ContentVersionStrategy
(MD5 哈希)是一个不错的选择,但有一些值得注意的例外(例如与模块加载器一起使用的 JavaScript 资源)。
You can use the VersionResourceResolver
for versioned resource URLs based on an MD5 hash
computed from the content, a fixed application version, or other information. A
ContentVersionStrategy
(MD5 hash) is a good choice with some notable exceptions (such as
JavaScript resources used with a module loader).
以下示例展示如何在 Java 配置中使用 VersionResourceResolver
:
The following example shows how to use VersionResourceResolver
in your Java configuration:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public/")
.resourceChain(true)
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public/")
.resourceChain(true)
.addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
}
}
可以使用 ResourceUrlProvider
重写 URL 并应用解析器和转换器的整个链(例如,插入版本)。WebFlux 配置提供了 ResourceUrlProvider
,以便可以将其注入到其他资源中。
You can use ResourceUrlProvider
to rewrite URLs and apply the full chain of resolvers and
transformers (for example, to insert versions). The WebFlux configuration provides a ResourceUrlProvider
so that it can be injected into others.
与 Spring MVC 不同,目前在 WebFlux 中,没有办法透明地重写静态资源 URL,因为没有视图技术可以利用非阻塞解析器和转换器链。仅提供本地资源时,变通办法是使用 ResourceUrlProvider
(例如,通过自定义元素)并阻塞。
Unlike Spring MVC, at present, in WebFlux, there is no way to transparently rewrite static
resource URLs, since there are no view technologies that can make use of a non-blocking chain
of resolvers and transformers. When serving only local resources, the workaround is to use
ResourceUrlProvider
directly (for example, through a custom element) and block.
请注意,当同时使用 EncodedResourceResolver
(例如,Gzip、Brotli 编码)和 VersionedResourceResolver
时,必须按该顺序注册它们,以确保始终根据未编码文件可靠地计算基于内容的版本。
Note that, when using both EncodedResourceResolver
(for example, Gzip, Brotli encoded) and
VersionedResourceResolver
, they must be registered in that order, to ensure content-based
versions are always computed reliably based on the unencoded file.
对于 WebJars,推荐使用版本化 URL,例如`/webjars/jquery/1.2.0/jquery.min.js`,并且是使用它们的最有效方法。上述资源位置在 Spring Boot 外部已配置(或可通过`ResourceHandlerRegistry`手动进行配置),并且无需添加`org.webjars:webjars-locator-core`依赖项。
For WebJars, versioned URLs like
/webjars/jquery/1.2.0/jquery.min.js
are the recommended and most efficient way to use them.
The related resource location is configured out of the box with Spring Boot (or can be configured
manually via ResourceHandlerRegistry
) and does not require to add the
org.webjars:webjars-locator-core
dependency.
通过 WebJarsResourceResolver
支持像 /webjars/jquery/jquery.min.js
这样的非版本化 URL,当 org.webjars:webjars-locator-core
库存在类路径中时,该解析器会自动注册,而代价是可能会减慢应用程序启动的类路径扫描。该解析器可以重写 URL 以包含 JAR 的版本,并且还可以匹配不带版本号的传入 URL——例如,从 /webjars/jquery/jquery.min.js
匹配到 /webjars/jquery/1.2.0/jquery.min.js
。
Version-less URLs like /webjars/jquery/jquery.min.js
are supported through the
WebJarsResourceResolver
which is automatically registered when the
org.webjars:webjars-locator-core
library is present on the classpath, at the cost of a
classpath scanning that could slow down application startup. The resolver can re-write URLs to
include the version of the jar and can also match against incoming URLs without versions — for example, from /webjars/jquery/jquery.min.js
to /webjars/jquery/1.2.0/jquery.min.js
.
基于 |
The Java configuration based on |
Path Matching
你可以自定义与路径匹配相关的选项。有关单个选项的详细信息,请参阅“https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/reactive/config/PathMatchConfigurer.html[PathMatchConfigurer
]”javadoc。以下示例展示了如何使用“PathMatchConfigurer
”:
You can customize options related to path matching. For details on the individual options, see the
PathMatchConfigurer
javadoc.
The following example shows how to use PathMatchConfigurer
:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
@Override
fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}
}
Spring WebFlux 依赖请求路径的已解析表示形式,称为 Spring WebFlux relies on a parsed representation of the request path called
与 Spring MVC 不同,Spring WebFlux 也不支持后缀模式匹配,在 Spring MVC 中,我们也在 recommend 远离依赖它。 Spring WebFlux also does not support suffix pattern matching, unlike in Spring MVC, where we are also recommend moving away from reliance on it. |
Blocking Execution
WebFlux Java 配置允许你自定义 WebFlux 中的阻塞执行。
The WebFlux Java config allows you to customize blocking execution in WebFlux.
你可以通过提供一个 AsyncTaskExecutor
,例如“https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/task/VirtualThreadTaskExecutor.html[VirtualThreadTaskExecutor
]”,以便在独立的线程上调用阻塞控制器方法,如下所示:
You can have blocking controller methods called on a separate thread by providing
an AsyncTaskExecutor
such as the
VirtualThreadTaskExecutor
as follows:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureBlockingExecution(BlockingExecutionConfigurer configurer) {
AsyncTaskExecutor executor = ...
configurer.setExecutor(executor);
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
@Override
fun configureBlockingExecution(configurer: BlockingExecutionConfigurer) {
val executor = ...
configurer.setExecutor(executor)
}
}
默认情况下,返回类型不被配置的 ReactiveAdapterRegistry
识别的控制器方法被认为是阻塞的,但您可以通过 BlockingExecutionConfigurer
设置自定义控制器方法谓词。
By default, controller methods whose return type is not recognized by the configured
ReactiveAdapterRegistry
are considered blocking, but you can set a custom controller
method predicate via BlockingExecutionConfigurer
.
WebSocketService
WebFlux Java 配置声明一个 WebSocketHandlerAdapter
bean,它为 WebSocket 处理程序的调用提供支持。这意味着要处理 WebSocket 握手请求,剩下的就是通过 SimpleUrlHandlerMapping
将 WebSocketHandler
映射到 URL。
The WebFlux Java config declares of a WebSocketHandlerAdapter
bean which provides
support for the invocation of WebSocket handlers. That means all that remains to do in
order to handle a WebSocket handshake request is to map a WebSocketHandler
to a URL
via SimpleUrlHandlerMapping
.
在某些情况下,可能需要使用提供的 WebSocketService
服务创建 WebSocketHandlerAdapter
bean,它允许配置 WebSocket 服务器属性。例如:
In some cases it may be necessary to create the WebSocketHandlerAdapter
bean with a
provided WebSocketService
service which allows configuring WebSocket server properties.
For example:
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public WebSocketService getWebSocketService() {
TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
strategy.setMaxSessionIdleTimeout(0L);
return new HandshakeWebSocketService(strategy);
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
@Override
fun webSocketService(): WebSocketService {
val strategy = TomcatRequestUpgradeStrategy().apply {
setMaxSessionIdleTimeout(0L)
}
return HandshakeWebSocketService(strategy)
}
}
Advanced Configuration Mode
@EnableWebFlux
导入 DelegatingWebFluxConfiguration
:
@EnableWebFlux
imports DelegatingWebFluxConfiguration
that:
-
Provides default Spring configuration for WebFlux applications
-
detects and delegates to
WebFluxConfigurer
implementations to customize that configuration.
对于高级模式,您可以移除 @EnableWebFlux
并直接扩展自 DelegatingWebFluxConfiguration
,而不是实现 WebFluxConfigurer
,如下例所示:
For advanced mode, you can remove @EnableWebFlux
and extend directly from
DelegatingWebFluxConfiguration
instead of implementing WebFluxConfigurer
,
as the following example shows:
-
Java
-
Kotlin
@Configuration
public class WebConfig extends DelegatingWebFluxConfiguration {
// ...
}
@Configuration
class WebConfig : DelegatingWebFluxConfiguration {
// ...
}
您可以在 WebConfig
中保留现有方法,但现在您还可以覆盖基础类的 bean 声明,并在类路径上仍然拥有任意数量的其他 WebMvcConfigurer
实现。
You can keep existing methods in WebConfig
, but you can now also override bean declarations
from the base class and still have any number of other WebMvcConfigurer
implementations on
the classpath.