響應式 Web 應用程式

Spring Boot 透過為 Spring Webflux 提供自動配置來簡化響應式Web應用程式的開發。

“Spring WebFlux 框架”

Spring WebFlux 是 Spring Framework 5.0 中引入的全新響應式 Web 框架。與 Spring MVC 不同,它不需要 servlet API,是完全非同步和非阻塞的,並透過 Reactor 專案實現了 Reactive Streams 規範。

Spring WebFlux 有兩種形式:函式式和基於註解式。基於註解的 WebFlux 非常接近 Spring MVC 模型,如以下示例所示:

  • Java

  • Kotlin

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/users")
public class MyRestController {

	private final UserRepository userRepository;

	private final CustomerRepository customerRepository;

	public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) {
		this.userRepository = userRepository;
		this.customerRepository = customerRepository;
	}

	@GetMapping("/{userId}")
	public Mono<User> getUser(@PathVariable Long userId) {
		return this.userRepository.findById(userId);
	}

	@GetMapping("/{userId}/customers")
	public Flux<Customer> getUserCustomers(@PathVariable Long userId) {
		return this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);
	}

	@DeleteMapping("/{userId}")
	public Mono<Void> deleteUser(@PathVariable Long userId) {
		return this.userRepository.deleteById(userId);
	}

}
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

@RestController
@RequestMapping("/users")
class MyRestController(private val userRepository: UserRepository, private val customerRepository: CustomerRepository) {

	@GetMapping("/{userId}")
	fun getUser(@PathVariable userId: Long): Mono<User> {
		return userRepository.findById(userId)
	}

	@GetMapping("/{userId}/customers")
	fun getUserCustomers(@PathVariable userId: Long): Flux<Customer> {
		return userRepository.findById(userId).flatMapMany { user: User ->
			customerRepository.findByUser(user)
		}
	}

	@DeleteMapping("/{userId}")
	fun deleteUser(@PathVariable userId: Long): Mono<Void> {
		return userRepository.deleteById(userId)
	}

}

WebFlux 是 Spring Framework 的一部分,詳細資訊可在其參考文件中找到。

“WebFlux.fn”,即函式式變體,將路由配置與請求的實際處理分離,如以下示例所示:

  • Java

  • Kotlin

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {

	private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);

	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(MyUserHandler userHandler) {
		return route()
				.GET("/{user}", ACCEPT_JSON, userHandler::getUser)
				.GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers)
				.DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser)
				.build();
	}

}
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.web.reactive.function.server.RequestPredicates.DELETE
import org.springframework.web.reactive.function.server.RequestPredicates.GET
import org.springframework.web.reactive.function.server.RequestPredicates.accept
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.RouterFunctions
import org.springframework.web.reactive.function.server.ServerResponse

@Configuration(proxyBeanMethods = false)
class MyRoutingConfiguration {

	@Bean
	fun monoRouterFunction(userHandler: MyUserHandler): RouterFunction<ServerResponse> {
		return RouterFunctions.route(
			GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
			GET("/{user}/customers").and(ACCEPT_JSON), userHandler::getUserCustomers).andRoute(
			DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser)
	}

	companion object {
		private val ACCEPT_JSON = accept(MediaType.APPLICATION_JSON)
	}

}
  • Java

  • Kotlin

import reactor.core.publisher.Mono;

import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

@Component
public class MyUserHandler {

	public Mono<ServerResponse> getUser(ServerRequest request) {
		...
	}

	public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
		...
	}

	public Mono<ServerResponse> deleteUser(ServerRequest request) {
		...
	}

}
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono

@Component
class MyUserHandler {

	fun getUser(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

	fun getUserCustomers(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

	fun deleteUser(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

}

“WebFlux.fn”是 Spring Framework 的一部分,詳細資訊可在其參考文件中找到。

您可以根據需要定義任意數量的 RouterFunction bean,以模組化路由器的定義。如果需要應用優先順序,可以對 bean 進行排序。

要開始使用,請將 spring-boot-starter-webflux 模組新增到您的應用程式中。

在您的應用程式中同時新增 spring-boot-starter-webspring-boot-starter-webflux 模組會導致 Spring Boot 自動配置 Spring MVC,而不是 WebFlux。之所以選擇此行為,是因為許多 Spring 開發人員將 spring-boot-starter-webflux 新增到其 Spring MVC 應用程式中以使用響應式 WebClient。您仍然可以透過將所選應用程式型別設定為 SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE) 來強制選擇。

Spring WebFlux 自動配置

Spring Boot 為 Spring WebFlux 提供了自動配置,適用於大多數應用程式。

自動配置在 Spring 預設設定的基礎上添加了以下功能:

如果您想保留 Spring Boot WebFlux 功能並新增額外的 WebFlux 配置,您可以新增自己的 @Configuration 型別的類 WebFluxConfigurer,但不帶 @EnableWebFlux

如果您想對自動配置的 HttpHandler 進行額外自定義,您可以定義 WebHttpHandlerBuilderCustomizer 型別的 bean,並使用它們修改 WebHttpHandlerBuilder

如果您想完全控制 Spring WebFlux,可以新增自己的用 @EnableWebFlux 註解的 @Configuration 類。

Spring WebFlux 轉換服務

如果您想自定義 Spring WebFlux 使用的 ConversionService,您可以提供一個具有 addFormatters 方法的 WebFluxConfigurer bean。

還可以使用 spring.webflux.format.* 配置屬性自定義轉換。未配置時,將使用以下預設值:

財產 DateTimeFormatter 格式

spring.webflux.format.date

ofLocalizedDate(FormatStyle.SHORT)

java.util.DateLocalDate

spring.webflux.format.time

ofLocalizedTime(FormatStyle.SHORT)

java.time 的 LocalTimeOffsetTime

spring.webflux.format.date-time

ofLocalizedDateTime(FormatStyle.SHORT)

java.time 的 LocalDateTimeOffsetDateTimeZonedDateTime

使用 HttpMessageReaders 和 HttpMessageWriters 的 HTTP 編解碼器

Spring WebFlux 使用 HttpMessageReaderHttpMessageWriter 介面來轉換 HTTP 請求和響應。它們透過 CodecConfigurer 進行配置,透過查詢類路徑中可用的庫來獲得合理的預設值。

Spring Boot 為編解碼器提供了專門的配置屬性 spring.http.codecs.*。它還透過使用 CodecCustomizer 例項應用進一步的自定義。例如,spring.jackson.* 配置鍵應用於 Jackson 編解碼器。

如果您需要新增或自定義編解碼器,可以建立自定義的 CodecCustomizer 元件,如以下示例所示:

  • Java

  • Kotlin

import org.springframework.boot.http.codec.CodecCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;

@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {

	@Bean
	public CodecCustomizer myCodecCustomizer() {
		return (configurer) -> {
			configurer.registerDefaults(false);
			configurer.customCodecs().register(new ServerSentEventHttpMessageReader());
			// ...
		};
	}

}
import org.springframework.boot.http.codec.CodecCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.http.codec.CodecConfigurer
import org.springframework.http.codec.ServerSentEventHttpMessageReader

class MyCodecsConfiguration {

	@Bean
	fun myCodecCustomizer(): CodecCustomizer {
		return CodecCustomizer { configurer: CodecConfigurer ->
			configurer.registerDefaults(false)
			configurer.customCodecs().register(ServerSentEventHttpMessageReader())
		}
	}

}

靜態內容

預設情況下,Spring Boot 從類路徑中名為 /static(或 /public/resources/META-INF/resources)的目錄提供靜態內容。它使用 Spring WebFlux 的 ResourceWebHandler,因此您可以透過新增自己的 WebFluxConfigurer 並重寫 addResourceHandlers 方法來修改該行為。

預設情況下,資源對映到 /**,但您可以透過設定 spring.webflux.static-path-pattern 屬性來調整。例如,將所有資源重定位到 /resources/** 可以透過以下方式實現:

  • 屬性

  • YAML

spring.webflux.static-path-pattern=/resources/**
spring:
  webflux:
    static-path-pattern: "/resources/**"

您還可以使用 spring.web.resources.static-locations 來自定義靜態資源位置。這樣做會用目錄位置列表替換預設值。如果您這樣做,預設的歡迎頁面檢測將切換到您的自定義位置。因此,如果在啟動時您的任何位置中存在 index.html,它將是應用程式的主頁。

除了前面列出的“標準”靜態資源位置外,還為 Webjars 內容設定了一個特殊情況。預設情況下,如果任何路徑為 /webjars/** 的資源以 Webjars 格式打包,則會從 jar 檔案中提供。可以透過 spring.webflux.webjars-path-pattern 屬性自定義路徑。

Spring WebFlux 應用程式不嚴格依賴 servlet API,因此它們不能部署為 war 檔案,也不使用 src/main/webapp 目錄。

歡迎頁面

Spring Boot 支援靜態和模板化的歡迎頁面。它首先在配置的靜態內容位置中查詢 index.html 檔案。如果未找到,則查詢 index 模板。如果找到其中之一,它將自動用作應用程式的歡迎頁面。

這僅作為應用程式定義的實際索引路由的後備。排序由 HandlerMapping bean 的順序定義,預設情況下如下:

org.springframework.web.reactive.function.server.support.RouterFunctionMapping

使用 RouterFunction bean 宣告的端點

org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping

@Controller bean 中宣告的端點

用於歡迎頁面的 RouterFunctionMapping

歡迎頁面支援

模板引擎

除了 REST Web 服務,您還可以使用 Spring WebFlux 來提供動態 HTML 內容。Spring WebFlux 支援各種模板技術,包括 Thymeleaf、FreeMarker 和 Mustache。

Spring Boot 包括對以下模板引擎的自動配置支援:

並非所有 FreeMarker 功能都支援 WebFlux。有關更多詳細資訊,請檢視每個屬性的描述。

當您使用這些模板引擎之一併採用預設配置時,您的模板將自動從 src/main/resources/templates 中獲取。

錯誤處理

Spring Boot 提供了一個 WebExceptionHandler,以合理的方式處理所有錯誤。它在處理順序中的位置緊鄰 WebFlux 提供的處理程式之前,後者被認為是最後處理的。對於機器客戶端,它會生成一個 JSON 響應,其中包含錯誤的詳細資訊、HTTP 狀態和異常訊息。對於瀏覽器客戶端,有一個“白標籤”錯誤處理程式,它以 HTML 格式呈現相同的資料。您還可以提供自己的 HTML 模板來顯示錯誤(請參閱下一節)。

在直接自定義 Spring Boot 中的錯誤處理之前,您可以利用 Spring WebFlux 中的 RFC 9457 問題詳細資訊支援。Spring WebFlux 可以生成帶有 application/problem+json 媒體型別的自定義錯誤訊息,例如:

{
	"type": "https://example.org/problems/unknown-project",
	"title": "Unknown project",
	"status": 404,
	"detail": "No project found for id 'spring-unknown'",
	"instance": "/projects/spring-unknown"
}

可以透過將 spring.webflux.problemdetails.enabled 設定為 true 來啟用此支援。

自定義此功能的第一步通常涉及使用現有機制,但替換或增加錯誤內容。為此,您可以新增一個 ErrorAttributes 型別的 bean。

要更改錯誤處理行為,您可以實現 ErrorWebExceptionHandler 並註冊該型別的 bean 定義。由於 ErrorWebExceptionHandler 級別相當低,Spring Boot 還提供了一個方便的 AbstractErrorWebExceptionHandler,允許您以 WebFlux 函式式方式處理錯誤,如以下示例所示:

  • Java

  • Kotlin

import reactor.core.publisher.Mono;

import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.webflux.autoconfigure.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.webflux.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder;

@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

	public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties,
			ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {
		super(errorAttributes, webProperties.getResources(), applicationContext);
		setMessageReaders(serverCodecConfigurer.getReaders());
		setMessageWriters(serverCodecConfigurer.getWriters());
	}

	@Override
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
		return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);
	}

	private boolean acceptsXml(ServerRequest request) {
		return request.headers().accept().contains(MediaType.APPLICATION_XML);
	}

	public Mono<ServerResponse> handleErrorAsXml(ServerRequest request) {
		BodyBuilder builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR);
		// ... additional builder calls
		return builder.build();
	}

}
import org.springframework.boot.autoconfigure.web.WebProperties
import org.springframework.boot.webflux.error.ErrorAttributes
import org.springframework.boot.webflux.autoconfigure.error.AbstractErrorWebExceptionHandler
import org.springframework.context.ApplicationContext
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.codec.ServerCodecConfigurer
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.RouterFunctions
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono

@Component
class MyErrorWebExceptionHandler(
		errorAttributes: ErrorAttributes, webProperties: WebProperties,
		applicationContext: ApplicationContext, serverCodecConfigurer: ServerCodecConfigurer
) : AbstractErrorWebExceptionHandler(errorAttributes, webProperties.resources, applicationContext) {

	init {
		setMessageReaders(serverCodecConfigurer.readers)
		setMessageWriters(serverCodecConfigurer.writers)
	}

	override fun getRoutingFunction(errorAttributes: ErrorAttributes): RouterFunction<ServerResponse> {
		return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml)
	}

	private fun acceptsXml(request: ServerRequest): Boolean {
		return request.headers().accept().contains(MediaType.APPLICATION_XML)
	}

	fun handleErrorAsXml(request: ServerRequest): Mono<ServerResponse> {
		val builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
		// ... additional builder calls
		return builder.build()
	}

}

為了更全面地瞭解,您還可以直接繼承 DefaultErrorWebExceptionHandler 並重寫特定方法。

在某些情況下,在控制器級別處理的錯誤不會被 Web 觀察或指標基礎設施記錄。應用程式可以透過在觀察上下文中設定已處理的異常來確保此類異常被觀察記錄。

自定義錯誤頁面

如果您想為給定的狀態碼顯示自定義 HTML 錯誤頁面,您可以新增從 error/* 解析的檢視,例如透過將檔案新增到 /error 目錄。錯誤頁面可以是靜態 HTML(即,新增到任何靜態資源目錄中)或使用模板構建。檔名稱應為精確的狀態碼、狀態碼系列掩碼,或者如果其他都不匹配,則為 error 作為預設值。請注意,預設錯誤檢視的路徑是 error/error,而 Spring MVC 中的預設錯誤檢視是 error

例如,要將 404 對映到靜態 HTML 檔案,您的目錄結構將如下所示:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

要使用 Mustache 模板對映所有 5xx 錯誤,您的目錄結構將如下所示:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>

Web 過濾器

Spring WebFlux 提供了一個 WebFilter 介面,可以實現該介面來過濾 HTTP 請求-響應交換。在應用程式上下文中找到的 WebFilter bean 將自動用於過濾每個交換。

當過濾器的順序很重要時,它們可以實現 Ordered 或使用 @Order 註解。Spring Boot 自動配置可能會為您配置 Web 過濾器。當它這樣做時,將使用下表中顯示的順序:

Web 過濾器 順序

WebFilterChainProxy (Spring Security)

-100

HttpExchangesWebFilter

Ordered.LOWEST_PRECEDENCE - 10

API 版本控制

Spring WebFlux 支援 API 版本控制,可用於隨著時間推移演進 HTTP API。同一個 @Controller 路徑可以多次對映以支援不同版本的 API。

有關更多詳細資訊,請參閱 Spring Framework 的參考文件

新增對映後,您還需要配置 Spring WebFlux,使其能夠使用請求傳送的任何版本資訊。通常,版本以 HTTP 頭、查詢引數或路徑的一部分形式傳送。

要配置 Spring WebFlux,您可以使用 WebFluxConfigurer bean 並重寫 configureApiVersioning(…​) 方法,或者您可以使用屬性。

例如,以下將使用 X-Version HTTP 頭獲取版本資訊,並在未傳送頭時預設為 1.0.0

  • 屬性

  • YAML

spring.webflux.apiversion.default=1.0.0
spring.webflux.apiversion.use.header=X-Version
spring:
  webflux:
    apiversion:
      default: 1.0.0
      use:
        header: X-Version

為了更全面的控制,您還可以定義 ApiVersionResolverApiVersionParserApiVersionDeprecationHandler bean,它們將被注入到自動配置的 Spring MVC 配置中。

API 版本控制在客戶端也受支援,包括 WebClientRestClient。有關詳細資訊,請參閱 API 版本控制

嵌入式響應式伺服器支援

Spring Boot 支援以下嵌入式響應式 Web 伺服器:Reactor Netty、Tomcat 和 Jetty。大多數開發人員使用適當的啟動器來獲取完全配置的例項。預設情況下,嵌入式伺服器偵聽埠 8080 上的 HTTP 請求。

自定義響應式伺服器

常見的響應式 Web 伺服器設定可以透過使用 Spring Environment 屬性進行配置。通常,您會在 application.propertiesapplication.yaml 檔案中定義這些屬性。

常見的伺服器設定包括:

  • 網路設定:傳入 HTTP 請求的偵聽埠(server.port)、要繫結的介面地址(server.address)等。

  • 錯誤管理:錯誤頁面的位置(spring.web.error.path)等。

  • SSL

  • HTTP 壓縮

Spring Boot 儘可能多地公開通用設定,但這並非總是可行的。對於這些情況,專門的名稱空間(例如 server.netty.*)提供特定於伺服器的自定義。

有關完整列表,請參閱 ServerProperties 類。

程式化自定義

如果您需要以程式設計方式配置您的響應式 Web 伺服器,您可以註冊一個實現 WebServerFactoryCustomizer 介面的 Spring Bean。WebServerFactoryCustomizer 提供對 ConfigurableReactiveWebServerFactory 的訪問,後者包含許多自定義設定器方法。以下示例展示了以程式設計方式設定埠:

  • Java

  • Kotlin

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> {

	@Override
	public void customize(ConfigurableReactiveWebServerFactory server) {
		server.setPort(9000);
	}

}
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.boot.web.server.reactive.ConfigurableReactiveWebServerFactory
import org.springframework.stereotype.Component

@Component
class MyWebServerFactoryCustomizer : WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> {

	override fun customize(server: ConfigurableReactiveWebServerFactory) {
		server.setPort(9000)
	}

}

JettyReactiveWebServerFactoryNettyReactiveWebServerFactoryTomcatReactiveWebServerFactoryConfigurableReactiveWebServerFactory 的專用變體,分別具有用於 Jetty、Reactor Netty 和 Tomcat 的額外自定義設定器方法。以下示例展示瞭如何自定義 NettyReactiveWebServerFactory,它提供對 Reactor Netty 特定配置選項的訪問:

  • Java

  • Kotlin

import java.time.Duration;

import org.springframework.boot.reactor.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class MyNettyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

	@Override
	public void customize(NettyReactiveWebServerFactory factory) {
		factory.addServerCustomizers((server) -> server.idleTimeout(Duration.ofSeconds(20)));
	}

}
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.boot.reactor.netty.NettyReactiveWebServerFactory
import org.springframework.stereotype.Component
import java.time.Duration

@Component
class MyNettyWebServerFactoryCustomizer : WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

	override fun customize(factory: NettyReactiveWebServerFactory) {
		factory.addServerCustomizers({ server -> server.idleTimeout(Duration.ofSeconds(20)) })
	}

}

直接自定義 ConfigurableReactiveWebServerFactory

對於需要從 ReactiveWebServerFactory 擴充套件的更高階用例,您可以自行公開此類型別的 bean。

提供了許多配置選項的設定器。還提供了幾個受保護的方法“鉤子”,以防您需要做一些更奇特的事情。有關詳細資訊,請參閱 ConfigurableReactiveWebServerFactory API 文件。

自動配置的定製器仍將應用於您的自定義工廠,因此請謹慎使用該選項。

響應式伺服器資源配置

在自動配置 Reactor Netty 或 Jetty 伺服器時,Spring Boot 將建立特定的 bean,這些 bean 將向伺服器例項提供 HTTP 資源:ReactorResourceFactoryJettyResourceFactory

預設情況下,這些資源也將與 Reactor Netty 和 Jetty 客戶端共享,以獲得最佳效能,前提是:

  • 伺服器和客戶端使用相同的技術

  • 客戶端例項使用 Spring Boot 自動配置的 WebClient.Builder bean 構建

開發人員可以透過提供自定義的 ReactorResourceFactoryJettyResourceFactory bean 來覆蓋 Jetty 和 Reactor Netty 的資源配置 - 這將同時應用於客戶端和伺服器。

您可以在WebClient 執行時部分了解有關客戶端資源配置的更多資訊。

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