首先我们要弄明白Web Flux是什么?Spring webflux是一种编程范例,可以使用lambda函数风格(声明式风格)组合Spring Boot应用程序。Spring Webflux和Spring Web是两个完全不同的Web栈。 然而, Spring Webflux继续支持基于注解的编程模型。虽然这两个堆栈定义的端点可能看起来相似,但测试这种端点的方式是相当不同的
Spring Boot应用程序可以用命令风格(如传统Spring WebMVC)或函数风格(如Spring WebFlux)编写。下面是使用pring WebFlux三个注意点:
1.目前,spring boot支持Spring WebMVC或WebFlux模型,因此我们不能在一个应用程序中两者混合使用。如果使用pring WebFlux,就不应该使用@RestController注释,并不要在pom.xml中配置spring-boot-starter-web依赖。
2.REST端点应该在@Configuration注释的类上使用, 被定义为RouerFunction的一个Bean,既不是在@RestController注释类,也不是在@Controller注释上使用。
3.Web Flux支持Java 8 lamba表达式,Web MVC是同步阻塞的IO模型,而Web Flux是异步非阻塞的IO模型。
Web Flux有什么特点?
1.Spring WebFlux是异步,非阻塞的。
2.WebFlux有Mono,Flux两种集合类型。
3.Mono是0->1集合类型,比如Mono。
4.Flux是1->n集合类型,比如Flux<List>
5.Mono,Flux都是异步处理的,而集合对象基本上是同步的。
Web Flux(Netty)跟Web MVC(Servlet)优缺点?
1.Web Flux的效率(qps)比Web MVC高。
2.Web Flux的编程难度高,维护成本高,对于切面等不好编写。
Web Flux实践
与Web MVC类似。我们声明我们的路由类为 @Configuration,然后初始化一个Bean。
在Web Flux请求的接口是RequestServer,响应的接口是ResponseServer。
其中RouterFunction提供了route,通过在route这个方法我们设置RequestPredicates
的路由行为,从而达到接受请求。
问题:在使用maven管理webflux project时,spring-boot-starter-web和spring-boot-starter-webflux能否一起工作?
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
当两者一起时配置的并不是webflux web application, 仍然时一个spring mvc web application。
官方文档中有这么一段注解:很多开发者添加spring-boot-start-webflux到他们的spring mvc web applicaiton去是为了使用reactive WebClient. 如果希望更改webApplication 类型需要显示的设置,如SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE).
Spring WebFlux Framework
Spring WebFlux是一个新的 reactive web应用框架,自 Spring Framework 5.0引入。与Spring MVC不同的是,它不需要the Servlet API,是完全异步和非阻塞的,实现了Reactive Streams specification。
Spring WebFlux有两种方式: functional and annotation-based.
基于注解的方式很类似与Spring MVC model,如下面的例子:
@RestController
@RequestMapping("/users")
public class MyRestController {
@GetMapping("/{user}")
public Mono<User> getUser(@PathVariable Long user) {
// ...
}
@GetMapping("/{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long user) {
// ...
}
@DeleteMapping("/{user}")
public Mono<User> deleteUser(@PathVariable Long user) {
// ...
}
}
“WebFlux.fn”, the functional variant, 分开了路由配置routing configuration 和实际的请求handler,如下面的例子:
@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) {
// ...
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
// ...
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
// ...
}
}