Spring WebFlux框架
Spring 5于2017年9月发布了通用版本(GA)。从Spring 5开始,提供了全新的Web开发框架:以Reactor为基础的WebFlux框架。这预示着Spring开始全面拥抱Reactive Programming。在此之前,SpringWeb开发主要是以Spring MVC为主,现在Spring WebFlux已经与SpringMVC具有同等的地位。
Spring WebFlux简介
Spring MVC是为Servlet API和Servlet容器专门构建的。而Spring WebFlux是异步非阻塞的,支持在Netty、Undertow和Servlet3.1+容器之类的服务器上运行。Spring Boot 2默认WebFlux是基于Netty实现的。
如图12.3所示,Spring WebFlux与Spring MVC的Web注解是一致的,这样便减少了从Spring MVC迁移到Spring WebFlux的成本。
WebFlux框架开发的接口返回类型必须是Mono<T>或者是Flux<T>。
Flux和Mono是Reactor框架中的两个基本概念,它们都实现了
org.reactivestreams.Publisher接口,也就是说Mono与Flux都是发布者。Mono代表0~1个元素的发布者,Flux代表0~N个元素的发布者。
Mono类
上面提到Mono实现了Publisher接口,因此它也是一个发布者,只是发布0~1个元素。Mono类中典型的创建数据流的方法如表12.2所示。
下面是Mono创建数据流的几个示例:
//just()方法创建
Mono.just("hello mono").subscribe(System.out::println);
// justOrEmpty()方法创建
Mono.justOrEmpty(Optional.of("hello
mono")).subscribe(System.out::
println);
Mono.justOrEmpty("hello
mono").subscribe(System.out::println);
Mono.empty().subscribe(System.out::println);
Mono.error(new Throwable("error")).subscribe();
Mono.never().subscribe();
//fromCallable()方法创建
Mono.fromCallable(() -> "hello
mono").subscribe(System.out::println);
//fromSupplier()方法创建
Mono.fromSupplier(() -> "hello
mono").subscribe(System.out::println);
//fromFuture()方法创建
Mono.fromFuture(CompletableFuture.completedFuture("hello
mno")).
subscribe(System.out::println);
//create()方法创建
Mono.create(sink->{
sink.success("hello mono");
}).subscribe(System.out::println);
创建数据流之后,还可以在响应式流上通过声明的方式添加多种不同的操作函数。典型的操作函数如表12.3所示。
表12.3 Mono类的操作函数
下面是Mono数据流操作函数的例子:
//filter()方法的使用
Mono.just(10).filter(i -> i%2 ==
0).subscribe(System.out::println);
//zipWith()方法的使用
Mono.just("hello").zipWith(Mono.just("Mono")).subscribe(Syste
m.out::
println);
//mergeWith()方法的使用
Mono.just("hello").mergeWith(Mono.just("Mono")).subscribe(Sys
tem.out::
println);
//flatMap()方法的使用
Mono.just("hello").flatMap(x -> Mono.just(x + "
flux")).subscribe
(System.out::println);
Flux类
Flux与Mono的不同之处在于,作为发布者,Flux可以发布0~N个元素。Flux类创建数据流的方法如表12.4所示。
表12.4 Flux创建数据流的方法
下面是创建Flux的几个例子:
// just()方法创建
Flux.just("hello","flux").subscribe(System.out::println);
// fromArray()方法创建
Flux.fromArray(new String[]
{"hello","flux"}).subscribe(System.out::
println);
//range()方法创建
Flux.range(1, 5).subscribe(System.out::println);
// create()方法创建
Flux.create(sink -> {
for (int i = 0; i < 10; i++) {
sink.next(i);
}
sink.complete();
}).subscribe(System.out::println);
//generate()方法创建
Flux.generate(sink -> {
sink.next("hello");
sink.complete();
}).subscribe(System.out::println);
Flux在响应式流上的操作函数与Mono类似,如表12.5所示。
表12.5 Flux操作函数
下面是Flux操作函数的示例:
//使用filter()方法
Flux.range(1, 10).filter(i -> i%2 ==
0).subscribe(System.out::println);
//使用zipWith()方法
Flux.just("hello").zipWith(Flux.just("flux")).subscribe(Syste
m.out::
println);
// 使用reduce()方法
Flux.range(1, 10).reduce((x,y) -> x +
y).subscribe(System.out::println);
// 使用merge()方法
Flux.merge(Flux.just("hello"),Flux.just("flux")).subscribe(Sy
stem.
out::println);
// 使用flatMap()方法
Flux.just("hello").flatMap(x -> Flux.just(x + "
flux")).subscribe
(System.out::println);
Spring WebFlux示例
学习了Mono与Flux类之后,基本上就能了解WebFlux开发的原理。
相对于Spring MVC来说,WebFlux接口返回的只能是Mono或Flux类。下面给出两个接口的参考示例:
@RestController
@RequestMapping("/webFlux")
public class WebFluxApi {
@GetMapping("/mono")
public Mono<JSONObject> mono(){
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "0");
jsonObject.put("message", "hello mono!");
return Mono.just(jsonObject); //创建
Mono对象
}
@GetMapping("/flux")
public Flux<JSONObject> flux(){
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "0");
jsonObject.put("message", "hello flux!");
return Flux.just(jsonObject); //创建
Mono对象
}
}
在本地启动应用之后,分别访问
http://localhost/webFlux/mono接口,返回结果如下:
{
code: "0",
message: "hello mono!"
}
访问
http://localhost/webFlux/flux接口,返回结果如下:[
{
code: "0",
message: "hello flux!"
}
]