版本:2.1.5.RELEASE
章节:29.2 The “Spring WebFlux Framework”
Spring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,完全异步且无阻塞,并通过Reactor项目实现Reactive Streams规范。
Spring WebFlux有两种版本:基于功能和基于注解。
基于注解的这一类型非常接近Spring MVC模型,如以下示例所示:
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/users")
public class MyRestController {
@GetMapping("/{user}")
public Mono<User> getUser(@PathVariable Long user) {
// ...
return Mono.empty();
}
@GetMapping("/{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long user) {
// ...
return Flux.empty();
}
@DeleteMapping("/{user}")
public Mono<User> deleteUser(@PathVariable Long user) {
// ...
return Mono.empty();
}
}
基于功能,将路由配置与请求的实际处理分开,如以下示例所示:
@Configuration
public class RoutingConfiguration {
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
.andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
.andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
}
}
@Component
public class UserHandler {
public Mono<ServerResponse> getUser(ServerRequest request) {
// ...
return Mono.empty();
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
// ...
return Mono.empty();
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
// ...
return Mono.empty();
}
}
WebFlux是Spring Framework的一部分,详细信息可在其参考文档中找到。
您可以根据需要定义尽可能多的RouterFunction
bean来模块化路由器的定义。如果需要应用优先级,可以订购Bean。
首先,将spring-boot-starter-webflux
模块添加到您的应用程序中。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
dependency>
在应用程序中同时添加
spring-boot-starter-web
和spring-boot-starter-webflux
模块会导致Spring Boot自动配置Spring MVC
,而不是WebFlux
。选择此行为是因为许多Spring开发人员将spring-boot-starter-webflux
添加到他们的Spring MVC应用程序
中以使用反应式WebClient
。您仍然可以通过将所选应用程序类型设置为SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)
来强制执行您的选择。
Spring Boot为Spring WebFlux提供自动配置,适用于大多数应用程序。
自动配置在Spring的默认值之上添加了以下功能:
如果你想保留Spring Boot WebFlux功能,并且想要添加额外的WebFlux配置
,你可以添加自己的@Configuration
类,类型为WebFluxConfigurer
,但没有@EnableWebFlux
。
如果您想完全控制Spring WebFlux,可以添加自己的@Configuration注解并启动@EnableWebFlux
。
Spring WebFlux使用HttpMessageReader和HttpMessageWriter接口来转换HTTP请求和响应。通过查看类路径中可用的库,它们配置了CodecConfigurer以具有合理的默认值。
Spring Boot通过使用CodecCustomizer实例进一步自定义。例如,spring.jackson.*
配置键应用于Jackson编解码器。
如果需要添加或自定义编解码器,可以创建自定义CodecCustomizer组件,如以下示例所示:
import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return codecConfigurer -> {
// ...
};
}
}
您还可以利用Boot的自定义JSON序列化程序和反序列化程序。
默认情况下,Spring Boot从类路径中名为 /static(或/public或/resources或/META-INF/resources)的目录中提供静态内容。它使用Spring WebFlux中的ResourceWebHandler,以便您可以通过添加自己的WebFluxConfigurer并覆盖addResourceHandlers方法来修改该行为。
默认情况下,资源映射到 /**,但您可以通过设置spring.webflux.static-path-pattern属性
来调整它。例如,可以按如下方式将所有资源重新定位到 /resources/**
:
spring.webflux.static-path-pattern=/resources/**
您还可以使用spring.resources.static-locations
自定义静态资源位置。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果启动时在任何位置存在index.html,则它是应用程序的主页。
除了前面列出的“标准”静态资源位置之外,还为Webjars内容制作了一个特例。在 /webjars/**
中具有路径的任何资源都是从jar文件提供的,如果它们以Webjars格式打包的话。
Spring WebFlux应用程序并不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用 src/main/webapp 目录。
除REST Web服务外,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf
,FreeMarker
和Mustache
。
当您使用其中一个模板引擎和默认配置时,您的模板将自动从 src/main/resources/templates
中获取。
…
Spring WebFlux提供了一个WebFilter接口
,可以实现该接口来过滤HTTP请求 - 响应
交换。在应用程序上下文中找到的WebFilter bean将自动用于过滤每个交换。
如果过滤器的顺序很重要,则可以实现Ordered
或使用@Order进行注解
。Spring Boot自动配置可以为您配置Web过滤器。执行此操作时,将使用下表中显示的订单:
Web Filter | Order |
---|---|
MetricsWebFilter | Ordered.HIGHEST_PRECEDENCE + 1 |
WebFilterChainProxy | (Spring Security) -100 |
HttpTraceWebFilter | Ordered.LOWEST_PRECEDENCE - 10 |