响应式编程
1.reactor单独开发的依赖
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-bom</artifactId>
<version>2020.0.7</version>
</dependency>
2.序列的三种通知的类型
- onNext()方法表示包含正常元素的通知
- onomplete()方法表示序列结束的消息通知
- onError()方法表示序列出错的消息通知
触发消息通知的时候,以上三个同名方法将会被调用
3.消息发布的两个组件 flux与mono组件
3.1常见的操作符
1.数据的转换机制 转换-->过滤-->组合-->日志
2.被压响应的核心机制
i:存拉模式(虽有的)
ii:纯推送模式
iii:拉推混合模式
3.被压处理策略 枚举的 Overflowstrategy来定义被压策略的枚举类型
i:buffer缓存策略
ii:丢弃策略
iii:laster 获取上有组件的最新数据策略
iiii:error错误的处理策略
3.2.Flux组件详解
3.2.1创建Flux的方法
3.2.1.1创建flux的静态方法 Flux.just(); Flux.interval(); Flux.from-为前缀的方法
如果有了数组 itrator对象 stram流 通过from的方法创建Flux对象 有如下的方法
Flux.fromArray(); Flux.fromStream(); Flux.fromIterable()
快速创建整数的数据流方法 Flux.range() 年份或者序号的时候有用
Flux.range(2020,5);
创建定时序列
//等待两秒之后,生成一个从0开始逐步递增的无界序列 每200毫秒推送一次
Flux.interval(Duration.ofSeconds(2),Duration.ofMillis(200)).subscribe(System.out::println);
3.2.1.2 动态创建Flux对象,事先无法确定数量
通过generate创建无界数据流
Flux.generate(sink->{
sink.next("张三");
sink.next("lisi");
sink.complete();
}).subscribe(System.out::println);
通过generate创建创建多个无界数据流
Flux.generate(()->1,(i,sink)->{
sink.next("张三");
sink.next("lisi");
if (i == 5) {
sink.complete();
}
return ++i;
}).subscribe(System.out::println);
通过create创建Flux流的方法
Flux.create(sink -> {
for (int i=0;i<5;i++){
sink.next("ceshi"+i);
}
sink.complete();
}).subscribe(System.out::println);
3.2.Mono组件介绍
3.2.1创建mono对象,创建Flux在创建mono的时候依然适用
Mono.create(sink->{
sink.success("mono对象");
}).subscribe(System.out::println);
3.3Flux与Mono组件之间的转换
Mono和flux互转:
1.第一种:如果 flux 是空的, single 会返回一个 Mono.error, 消费的时候就会抛异常
Flux<String> flux;
Mono<List<String>> mono = flux.buffer().single()
2.第二种:collectList 是把数据存在内存里,注意数据量对内存的影响
Flux<String> flux;
Mono<List<String>> mono = flux.collectList();
3第三种:Mono -> Flux
List<A> list;
Flux<A> flux = Flux.fromIterable(list).collectList();
Flux<String> newFlux =listMono.flatMapMany(Flux::fromIterable);
下面只Flux与Mono转换后的测试案例
@GetMapping(value = "/3")
public Flux<UserInfo> get3() {
log.info("get2 start:" + Thread.currentThread().getName());
UserInfo zhangsan = new UserInfo(1L, "zhangsan", "222222");
UserInfo lisi = new UserInfo(1L, "lisi", "333333");
UserInfo wangwu = new UserInfo(1L, "wangwu", "444444");
Flux<UserInfo> map = Flux.fromArray(new UserInfo[]{zhangsan, lisi, wangwu}).map(s -> {
return s;
});
return map;
}
@GetMapping(value = "/5")
public Mono<List<UserInfo>> get5() {
UserInfo zhangsan = new UserInfo(1L, "zhangsan", "222222");
UserInfo lisi = new UserInfo(1L, "lisi", "333333");
UserInfo wangwu = new UserInfo(1L, "wangwu", "444444");
Flux<UserInfo> map = Flux.fromArray(new UserInfo[]{zhangsan, lisi, wangwu}).map(s -> {
return s;
});
return map.collectList();
}
通过apiPost访问得到的结果均是如下
[
{
"id": 1,
"username": "zhangsan",
"password": "222222"
},
{
"id": 1,
"username": "lisi",
"password": "333333"
},
{
"id": 1,
"username": "wangwu",
"password": "444444"
}
]
3.2订阅响应式流 subscribe订阅
3.3常见的操作符已经使用
3.1转换操作符
//buff转换肤的演示
Flux.range(1,25).buffer(10).subscribe(System.out::println);
输出结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
[21, 22, 23, 24, 25]
Flux.range(1,5).window(2).toIterable().forEach(w->{
w.subscribe(System.out::println);
System.out.println("=============");
});
输出结果:
1
2
=============
3
4
=============
5
=============
//map操作符
Flux.range(1,5).map(s-> "yuaus:"+s).subscribe(System.out::println);
输出结果:
yuaus:1
yuaus:2
yuaus:3
yuaus:4
yuaus:5
//flatmap操作符之后每一个元素依然是一个流
Flux.range(1, 5).flatMap(s -> Mono.just(s * s)).subscribe(System.out::println);
输出结果:
1
4
9
16
25
3.2过滤操作符 常用的包括 filter first/last skip/skipLast take/takeLast
3.3组合操作符 常用的组合操作符 then/when merge startWith zip 等
//then与thenMany操作符的演示
Flux.range(1,5).then(Mono.just(2)).subscribe(System.out::println);
输出结果 :2
Flux.range(1,5).thenMany(Mono.just(2)).subscribe(System.out::println);
同样输出的结果:2
then前面的不进行任何的操作
//when操作符进行数据的操作
Flux<Void> voidFlux = Flux.range(1, 5).flatMap(s -> {
Mono<String> just1 = Mono.just("just1" + s);
Mono<String> just2 = Mono.just("just2" + s);
return Mono.when(just1, just2);
});
//merger操作符的使用 每个都是非顺序输出的
Flux<Long> interval1 = Flux.interval(Duration.ofSeconds(1), Duration.ofMillis(200)).take(2);
Flux<Long> interval2 = Flux.interval(Duration.ofSeconds(1), Duration.ofMillis(200)).take(2);
Flux<Long> merge = Flux.merge(interval1, interval2);
merge.toStream().forEach(System.out::println);
输出的结果
0
0
1
1
//merger操作符的使用 每个都是顺序执行完再合并
Flux<Long> interval1 = Flux.interval(Duration.ofSeconds(1), Duration.ofMillis(200)).take(2);
Flux<Long> interval2 = Flux.interval(Duration.ofSeconds(1), Duration.ofMillis(200)).take(2);
Flux<Long> merge = Flux.mergeSequential(interval1, interval2);
merge.toStream().forEach(System.out::println);
输出的结果
0
1
0
1
//zip操作符 一对一的合并
Flux<Integer> integerFlux1 = Flux.fromArray(new Integer[]{1, 3});
Flux<Integer> integerFlux2 = Flux.fromArray(new Integer[]{2, 4});
Flux.zip(integerFlux1,integerFlux2).subscribe(System.out::println);
输出数据:
[1,2]
[3,4]
3.4条件操作符
//常见的操作符 defaultEmpty takeUtil takeWhile skipUtil skipWhile
defaultEmpty用来返回原来方法返回值的一种处理
@GetMapping(value = "/8")
public Mono<ResponseEntity<Integer>> get8() {
//when操作符进行数据的操作
Mono<ResponseEntity<Integer>> responseEntityMono = Mono.just(11).map(ResponseEntity::ok).defaultIfEmpty(ResponseEntity.status(404).body(null));
return responseEntityMono;
}
输出的结果是11