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 實現的更多資訊,請參閱 FormatterRegistrar SPIFormattingConversionServiceFactoryBean

驗證

預設情況下,如果類路徑上存在 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 的預設屬性

如果類路徑上檢測到以下眾所周知的模組,它還會自動註冊它們

檢視解析器

以下示例展示瞭如何配置檢視解析

  • 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))
	}
}

資源處理器還支援 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-lite 依賴。

無版本號的 URL,例如 /webjars/jquery/jquery.min.js,透過 WebJarsResourceResolver 支援,當類路徑中存在 org.webjars:webjars-locator-lite 庫時,該解析器會自動註冊。該解析器可以重寫 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 依賴於請求路徑的解析表示(稱為 RequestPath)來訪問已解碼的路徑段值,並去除了分號內容(即路徑或矩陣變數)。這意味著,與 Spring MVC 不同,您無需指示是否解碼請求路徑,也無需指示是否為路徑匹配目的去除分號內容。

Spring WebFlux 也不支援字尾模式匹配,與 Spring MVC 不同,在 Spring MVC 中,我們也 建議 放棄對其的依賴。

API 版本

要啟用 API 版本控制,請使用 WebFluxConfigurerApiVersionConfigurer 回撥

  • Java

  • Kotlin

@Configuration
public class WebConfiguration implements WebFluxConfigurer {

	@Override
	public void configureApiVersioning(ApiVersionConfigurer configurer) {
		configurer.useRequestHeader("API-Version");
	}
}
@Configuration
class WebConfiguration : WebMvcConfigurer {

	override fun configureApiVersioning(configurer: ApiVersionConfigurer) {
		configurer.useRequestHeader("API-Version")
	}
}

您可以透過以下內建選項之一解析版本,或者使用自定義的 ApiVersionResolver

  • 請求頭

  • 請求引數

  • 路徑段

  • 媒體型別引數

要從路徑段解析,您需要指定預期包含版本的路徑段的索引。路徑段必須宣告為 URI 變數,例如“/{version}”、“/api/{version}”等,其中實際名稱不重要。由於版本通常位於路徑的開頭,請考慮透過 路徑匹配 選項將其外部配置為所有處理程式的公共路徑字首。

預設情況下,版本透過 SemanticVersionParser 解析,但您也可以配置自定義的 ApiVersionParser

為了方便起見,WebFlux 會透明地從請求對映中宣告的版本中檢測支援的版本,但您可以透過 WebFlux 配置中的一個標誌將其關閉,並僅將配置中明確配置的版本視為支援的版本。帶有不支援版本的請求將被 InvalidApiVersionException 拒絕,並導致 400 響應。

您可以設定一個 ApiVersionDeprecationHandler 來向客戶端傳送有關已棄用版本的資訊。內建的標準處理程式可以根據 RFC 9745RFC 8594 設定“Deprecation”、“Sunset”和“Link”標頭。

一旦配置了 API 版本控制,您就可以根據請求版本將請求對映到 控制器方法

阻塞執行

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 握手請求,所有需要做的就是透過 SimpleUrlHandlerMappingWebSocketHandler 對映到一個 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 實現。

© . This site is unofficial and not affiliated with VMware.