Boot WebFlux-响应式编程-1(学习笔记 2021.03.26)
Spring Boot WebFlux (学习笔记-12021.03.26)前言:(SpringWebFlux官网)(Reactive官网)Spring MVC Web架构是基于阻塞式Servlet API构建的。Servlet 3.1后提供了非阻塞APISpring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Serv
Spring Boot WebFlux (学习笔记-1 2021.03.26)
前言: (SpringWebFlux官网) (Reactive官网)
Spring MVC Web
架构是基于阻塞式Servlet API
构建的。Servlet 3.1
后提供了非阻塞API
Spring WebFlux
是Spring Framework 5.0
中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且无阻塞的,并通过Reactor项目实现Reactive Streams规范, Spring WebFlux有两种形式:功能性的和基于注释的。基于注释的模型非常类似于Spring MVC模型;而
Spring Boot 2.0 以后版本
才是基于Spring Framework 5.0
进行构建的, 如果需要使用Spring WebFlux
版本必须大于2.0
其优势在与:
Spring WebFlux 是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。
WebFlux 并不能使接口的响应时间缩短,它仅仅能够提升吞吐量和伸缩性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ku3CePLa-1616768287147)(https://docs.spring.io/spring-framework/docs/5.3.1/reference/html/images/spring-mvc-and-webflux-venn.png)]
从图可以看到Spring WebFlux是非阻塞式的, 同样支持
@Controller
注解, 在Netty,Undertow和Servlet 3.1+容器等服务器上运行, 支持 Reactive Streams,并其目前只支持非关系型数据库,如Mongo,Redis等。
Spring MVC
能满足场景的,就不需要更改为Spring WebFlux
。要注意容器的支持,可以看看底层 内嵌容器 的支持。
微服务 体系结构,
Spring WebFlux
和Spring MVC
可以混合使用。尤其开发IO
密集型 服务的时候,可以选择Spring WebFlux
去实现。下面进行快速入门学习
1.0 项目基于SpringBoot 2.2.0
版本
1.1.1 引入依赖webflux
替换web
依赖
<artifactId>spring-boot-starter-web</artifactId>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Reactor 是Spring WebFlux所使用的响应式库,其提供了两个特殊的类
Mono
和Flux
。Mono和Flux在发布订阅模式中都属于发布者(不清楚的可以参考Java 9 Flow API学习),查看源码会发现它们都实现了Publisher接口。
Mono表示0 ~ 1个元素的数据发布者,Flux表示 0 ~ N个元素的数据发布者。我们可以通过一个例子来了解Mono和Flux
@Test
public void contextLoads() {
Integer i = 88;
// Mono发布者发布一个数据
Mono.fromSupplier(() -> i + 12)
// 消费发布数据
.subscribe(integer -> System.out.println(integer));
// Flux发布者发布多个数据
Integer[] arr = {88, 22};
Flux.fromArray(arr)
.map(integer -> integer + 1)
// 消费发布数据
.subscribe(integer ->
System.out.println(integer)
);
}
1.1.2 返回值Mono
在Controller
控制层用法
@RestController
@RequestMapping("/web")
public class WebFluxController {
@Autowired
private SleepService sleepService; //此service 方法只是 TimeUnit.SECONDS.sleep(2); 睡眠2秒, 然后返回字符串
@GetMapping("/test1")
public String test1(){
long start = System.currentTimeMillis();
System.out.println("test1开始执行");
String sleep = sleepService.sleep("困");
long end = System.currentTimeMillis() - start;
String str = "test1耗时:" + end + "毫秒, 原因" + sleep;
System.out.println(str);
return str;
}
@GetMapping("/test2")
public Mono<String> test2(){
long start = System.currentTimeMillis();
System.out.println("test2开始执行");
Mono<String> mono = Mono.fromSupplier(() -> sleepService.sleep("困"));
long end = System.currentTimeMillis() - start;
System.out.println("test2耗时:"+end+"毫秒, 原因"+mono.block());
return mono;
}
@GetMapping("/test3")
public Mono<String> test3() {
System.out.println("test3开始执行");
logger.info("线程名称:{}",Thread.currentThread().getName());
String sleep = sleepService.sleep("困");
return Mono.just(sleep);
}
}
进行访问后的控制台结果:
test1开始执行
test1耗时:2001毫秒, 原因困睡觉结束
test2开始执行
test2耗时:6毫秒, 原因困睡觉结束
可以看到
test2
方法里的Mono<String> mono = Mono.fromSupplier(() -> sleepService.sleep("困"))
是异步非阻塞的,不用等待service业务执行完成, 就能继续往下执行, 但是注意并不能加快响应速度, 通常使用的是Mono.just(sleep)
, 并且浏览器返回的也是service
返回的字符串
1.1.3 返回值 Flux
在Controller
控制层用法
@GetMapping(value = "/test4",produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> test4() {
long start = System.currentTimeMillis();
System.out.println("test4开始执行");
Flux<String> fromArray = Flux.fromStream(
() -> Stream.of(sleepService.sleep("kun"),"另一个方法")
);
long end = System.currentTimeMillis() - start;
System.out.println("test4耗时:" + end + "毫秒");
return fromArray;
}
@GetMapping("/test5")
public Mono<String> test5() {
System.out.println("test5开始执行");
logger.info("线程名称:{}",Thread.currentThread().getName());
String sleep = sleepService.sleep("困");
return Flux.just(sleep);
}
扩展:
Mono,Flux常用方法
Flux
可以通过Flux类的静态方法来生成:
just()
:可以指定序列中包含的全部元素。创建出来的 Flux 序列在发布这些元素之后会自动结束。fromArray()
,fromIterable()
和fromStream()
:可以从一个数组、Iterable 对象或 Stream 对象中创建 Flux 对象。empty()
:创建一个不包含任何元素,只发布结束消息的序列。error(Throwable error)
:创建一个只包含错误消息的序列。never()
:创建一个不包含任何消息通知的序列。range(int start, int count)
:创建包含从 start 起始的 count 个数量的 Integer 对象的序列。interval(Duration period)
和interval(Duration delay, Duration period)
:创建一个包含了从 0 开始递增的 Long 对象的序列。其中包含的元素按照指定的间隔来发布。除了间隔时间之外,还可以指定起始元素发布之前的延迟时间。
Mono
Mono 的创建方式与之前介绍的 Flux 比较相似。Mono 类中也包含了一些与 Flux 类中相同的静态方法。这些方法包括 just(),empty(),error()和 never()等。除了这些方法之外,Mono 还有一些独有的静态方法:
fromCallable()
、fromCompletionStage()
、fromFuture()
、fromRunnable(
)和fromSupplier()
:分别从 Callable、CompletionStage、CompletableFuture、Runnable 和 Supplier 中创建 Mono。delay(Duration duration)
:创建一个 Mono 序列,在指定的延迟时间之后,产生数字 0 作为唯一值。ignoreElements(Publisher<T> source)
:创建一个 Mono 序列,忽略作为源的 Publisher 中的所有元素,只产生结束消息。justOrEmpty(Optional<? extends T> data)
和justOrEmpty(T data)
:从一个 Optional 对象或可能为 null 的对象中创建 Mono。只有 Optional 对象中包含值或对象不为 null 时,Mono 序列才产生对应的元素。
1
更多推荐
所有评论(0)