WebFlux 配置
WebFlux Java 配置宣告了使用註解控制器或函數式端點處理請求所需的組件,並提供 API 來自訂配置。這表示您不需要了解 Java 配置建立的基礎 Bean。但是,如果您想了解它們,可以在 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 在剖析和格式化日期值時會考量請求地區設定。這適用於日期表示為具有「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 SPI 和 FormattingConversionServiceFactoryBean ,以取得有關何時使用 FormatterRegistrar 實作的更多資訊。 |
驗證
預設情況下,如果 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 訊息編解碼器
下列範例示範如何自訂讀取和寫入請求和回應 Body 的方式
-
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 框架整合的視圖技術的捷徑。下列範例使用 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
實作鏈,可用於建立工具鏈以處理最佳化資源。
您可以針對基於從內容計算出的 MD5 雜湊、固定應用程式版本或其他資訊的版本化資源 URL 使用 VersionResourceResolver
。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 MVC 不同,Spring WebFlux 也不支援後綴模式匹配,在 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 宣告,並且在類別路徑上仍然可以有任意數量的其他 WebMvcConfigurer
實作。