WebFlux 配置
WebFlux Java 配置聲明瞭使用帶註解的控制器或函式式端點處理請求所需的元件,並提供了一個用於自定義配置的 API。這意味著您無需瞭解 Java 配置建立的底層 beans。但是,如果您想了解它們,可以在 WebFluxConfigurationSupport
中檢視,或在 特殊 Bean 型別 中閱讀更多關於它們的資訊。
對於更高階的自定義(配置 API 中未提供),您可以透過高階配置模式完全控制配置。
啟用 WebFlux 配置
您可以在 Java 配置中使用 @EnableWebFlux
註解,示例如下
-
Java
-
Kotlin
@Configuration
@EnableWebFlux
public class WebConfig {
}
@Configuration
@EnableWebFlux
class WebConfig
使用 Spring Boot 時,您可能希望使用型別為 WebFluxConfigurer 的 @Configuration 類,但不帶 @EnableWebFlux ,以保留 Spring Boot WebFlux 的自定義設定。更多詳情請參閱WebFlux 配置 API 部分和專門的 Spring Boot 文件。 |
前面的示例註冊了多個 Spring WebFlux 基礎設施 bean,並適應類路徑上可用的依賴項,例如 JSON、XML 等。
WebFlux 配置 API
在您的 Java 配置中,您可以實現 WebFluxConfigurer
介面,示例如下
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
// Implement configuration methods...
}
@Configuration
class WebConfig : WebFluxConfigurer {
// Implement configuration methods...
}
轉換、格式化
預設情況下,會安裝各種數字和日期型別的格式化程式,並支援透過在欄位和引數上使用 @NumberFormat
、@DurationFormat
和 @DateTimeFormat
進行自定義。
要在 Java 配置中註冊自定義格式化程式和轉換器,請使用以下方法
-
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 在解析和格式化日期值時會考慮請求的 Locale。這適用於透過“input”表單欄位將日期表示為字串的表單。然而,對於“date”和“time”表單欄位,瀏覽器會使用 HTML 規範中定義的固定格式。對於這種情況,日期和時間格式化可以按如下方式自定義
-
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)
}
}
有關何時使用 FormatterRegistrar 實現的更多資訊,請參閱 FormatterRegistrar SPI 和 FormattingConversionServiceFactoryBean 。 |
驗證
預設情況下,如果類路徑上存在Bean Validation(例如 Hibernate Validator),則 LocalValidatorFactoryBean
會註冊為一個全域性驗證器,用於 @Controller
方法引數上的 @Valid
和 @Validated
。
在您的 Java 配置中,您可以自定義全域性 Validator
例項,示例如下
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public Validator getValidator() {
// ...
}
}
@Configuration
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 配置中宣告的 bean 發生衝突。 |
內容型別解析器
您可以配置 Spring WebFlux 如何從請求中確定 @Controller
例項所需的媒體型別。預設情況下,僅檢查 Accept
頭,但您也可以啟用基於查詢引數的策略。
以下示例展示瞭如何自定義請求的內容型別解析
-
Java
-
Kotlin
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configureContentTypeResolver(RequestedContentTypeResolverBuilder builder) {
// ...
}
}
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configureContentTypeResolver(builder: RequestedContentTypeResolverBuilder) {
// ...
}
}
HTTP 訊息編解碼器
以下示例展示瞭如何自定義請求體和響應體的讀取和寫入方式
-
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
提供了一組預設的讀取器和寫入器。您可以使用它來新增更多讀取器和寫入器,自定義預設的,或完全替換預設的。
對於 Jackson JSON 和 XML,考慮使用 Jackson2ObjectMapperBuilder
,它會透過以下屬性自定義 Jackson 的預設屬性
如果在類路徑上檢測到以下知名模組,它還會自動註冊
-
jackson-datatype-jsr310
:支援 Java 8 日期和時間 API 型別。 -
jackson-datatype-jdk8
:支援其他 Java 8 型別,如Optional
。 -
jackson-module-kotlin
:支援 Kotlin 類和資料類。
檢視解析器
以下示例展示瞭如何配置檢視解析
-
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 檢視技術)
-
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
實現,示例如下
-
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
}
}
為了支援內容協商以及透過檢視解析渲染其他格式(除了 HTML),您可以基於 HttpMessageWriterView
實現配置一個或多個預設檢視,該實現接受來自 spring-web
的任何可用編解碼器。以下示例展示瞭如何配置
-
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))
}
// ...
}
有關與 Spring WebFlux 整合的檢視技術的更多資訊,請參閱檢視技術。
靜態資源
此選項提供了一種便捷的方式,從基於Resource
的位置列表中提供靜態資源。
在下一個示例中,對於以 /resources
開頭的請求,相對路徑用於查詢並提供類路徑上相對於 /static
的靜態資源。資源會設定一年後的過期時間,以確保最大程度地利用瀏覽器快取並減少瀏覽器發出的 HTTP 請求。還會評估 Last-Modified
頭,如果存在,則返回 304
狀態碼。以下列表顯示了該示例
-
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))
}
}
另請參閱靜態資源的 HTTP 快取支援。
資源處理器還支援一個由ResourceResolver
實現和ResourceTransformer
實現組成的鏈,可用於構建處理最佳化資源的工具鏈。
您可以使用 VersionResourceResolver
為基於從內容計算的 MD5 雜湊、固定應用版本或其他資訊的版本化資源 URL。對於大多數情況,ContentVersionStrategy
(MD5 雜湊) 是個不錯的選擇,但也有一些明顯的例外(例如與模組載入器一起使用的 JavaScript 資源)。
以下示例展示瞭如何在 Java 配置中使用 VersionResourceResolver
-
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
,以便可以將其注入到其他元件中。
與 Spring MVC 不同,目前在 WebFlux 中無法透明地重寫靜態資源 URL,因為沒有檢視技術可以使用非阻塞的解析器和轉換器鏈。當只提供本地資源時,解決方法是直接使用 ResourceUrlProvider
(例如,透過自定義元素)並阻塞。
請注意,同時使用 EncodedResourceResolver
(例如,Gzip、Brotli 編碼)和 VersionedResourceResolver
時,必須按此順序註冊它們,以確保基於內容的版本始終可靠地基於未編碼的檔案計算。
對於 WebJars,使用版本化 URL,如 /webjars/jquery/1.2.0/jquery.min.js
,是推薦且最有效的方式。相關的資源位置在 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
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.method.HandlerTypePredicate;
import org.springframework.web.reactive.config.PathMatchConfigurer;
import org.springframework.web.reactive.config.WebFluxConfigurer;
@Configuration
public class WebConfig implements WebFluxConfigurer {
@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
import org.springframework.context.annotation.Configuration
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.method.HandlerTypePredicate
import org.springframework.web.reactive.config.PathMatchConfigurer
import org.springframework.web.reactive.config.WebFluxConfigurer
@Configuration
class WebConfig : WebFluxConfigurer {
override fun configurePathMatching(configurer: PathMatchConfigurer) {
configurer.addPathPrefix(
"/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}
}
Spring WebFlux 依賴於名為 Spring WebFlux 也不支援字尾模式匹配,與 Spring MVC 不同,我們在 Spring MVC 中也建議不再依賴它。 |
阻塞執行
WebFlux Java 配置允許您自定義 WebFlux 中的阻塞執行。
您可以透過提供一個 AsyncTaskExecutor
(例如VirtualThreadTaskExecutor
)來讓阻塞的控制器方法在單獨的執行緒上呼叫,如下所示
-
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
設定自定義的控制器方法謂詞。
WebSocketService
WebFlux Java 配置聲明瞭一個 WebSocketHandlerAdapter
bean,它為 WebSocket 處理器提供呼叫支援。這意味著為了處理 WebSocket 握手請求,只需透過 SimpleUrlHandlerMapping
將 WebSocketHandler
對映到 URL 即可。
在某些情況下,可能需要使用提供的 WebSocketService
服務建立 WebSocketHandlerAdapter
bean,該服務允許配置 WebSocket 伺服器屬性。例如
-
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)
}
}
高階配置模式
@EnableWebFlux
匯入了 DelegatingWebFluxConfiguration
,它會
-
為 WebFlux 應用提供預設的 Spring 配置
-
檢測並委託給
WebFluxConfigurer
實現來定製該配置。
對於高階模式,您可以移除 @EnableWebFlux
,並直接繼承 DelegatingWebFluxConfiguration
,而不是實現 WebFluxConfigurer
,示例如下
-
Java
-
Kotlin
@Configuration
public class WebConfig extends DelegatingWebFluxConfiguration {
// ...
}
@Configuration
class WebConfig : DelegatingWebFluxConfiguration {
// ...
}
您可以保留 WebConfig
中的現有方法,但現在您也可以重寫基類中的 bean 宣告,並且仍然可以在 classpath 中擁有任意數量的其他 WebMvcConfigurer
實現。