Project Reactor 常用 API 总结

Reactor 简介

Reactor 是完全异步非阻塞的响应式编程 JVM 框架,它能通过背压 backpressure 的方式来实现对元素需求的管理。

它提供了跟Java8 函数式接口的集成,例如 CompletableFuture, Stream 和 Duration;并主要提供两个异步序列接口 Flux(N个元素) 和 Mono(0-1个元素),并严格遵循响应式流 Reactive Streams 的JVM规范。

核心依赖

需要JDK基线版本8或以上

在pom中引入下列库依赖进行使用

<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-core</artifactId>
    <version>3.4.21</version>
</dependency>

若需要进行测试用例的编写,加入下列依赖

<dependency>
    <groupId>io.projectreactor</groupId>
    <artifactId>reactor-test</artifactId>
    <version>3.4.10</version>

</dependency>

Mono/Flux 创建方式

just

简单元素生成

Flux.just("a", "b", "c");

fromIterable

从 Iterable 接口实现类(能够使用for-each循环的数据结构)生成。Mono只有0-1个元素,所以语义定义上没有从Iterable创建的必要。

  Flux.fromIterable(Arrays.asList("a", "b", "c"));

fromArray

从数组生成

  Flux.fromArray(new String[]{"a", "b", "c"});

fromStream

此处为与Java Stream的集成

Flux.fromStream(Stream.of(new String[]{"a", "b", "c"}));

generate

generate 是同步且逐个发送元素的流创建方法,逐次发送意味着每次回调最多只能调用一次 next() 方法(虽然可以有选择地调用 error(Throwable) 或 complete())

一般情况下我们会使用一个变量记录当前 sink 的状态。

  Flux.generate(
      AtomicLong::new,
      (state, sink) -> {
          long i = state.getAndIncrement();
          sink.next(i);
          if (i == 10) sink.complete();
          return state;
      },
      (state) -> System.out.println("I'm done")
  );

create

create 跟 generate 的不同点在于

  • create 在一次方法调用中可以多次调用 next() 发送多个元素
  • 没有表达可变状态的变量

一般它被用于转化其他异步的 API(比如listener)将其集成到 reactor框 架中来,并且我们可以在 create 方法中指定背压策略 OverflowStrategy

  Flux.create(sink -> {
     //pretend we are registering a listener here
        new MyDataListener(){
            public void onReceiveData(String str){
                sink.next(str);
            }
            public void onComplete(){
                sink.complete();
            }
        };
  }, FluxSink.OverflowStrategy.DROP);

常用的背压策略有下列几种:

  • IGNORE 忽略下游的背压请求
  • ERROR 下游消费过慢的时候会抛出一个IllegalStateException
  • DROP 下游消费过慢的时候,就drop掉这个信号
  • LATEST 下游指挥拿到上游发送的最新的信号,这个如果是一个实时信息流的话会很有用
  • BUFFER 也就是默认策略,如果下游消费过慢的话,就会存进一个缓存,要注意这个缓存是会无限增长的,堆积过多会内存溢出

push

和 create 类似,不过当中的 next,complete,error 方法只能由一个线程调用,适用于单一 Producer 的场景

其他

  • Flux#range 从整数范围进行遍历
  • Mono#justOrEmpty 从可能是null值的生成元素
  • Mono#fromSupplier 从Supplier生成单一元素
  • Mono#fromRunnable 从一个Runnable Task生成单一元素
  • Mono#fromFuture 从CompletableFuture生成单一元素
  • empty 空元素集
  • error 立即抛出异常
  • defer 推迟到订阅时执行
  • using 从disposable source生成元素流

操作Mono/Flux

map

通过 mapper 对元素进行转换操作

  map(Function<? super T, ? extends V> mapper)

  Flux<Integer> ints = Flux.range(1, 4);
  Flux<Integer> mapped = ints.map(i -> i * 2);
filter

通过给定 Predicate 对每个元素进行判断,如果条件为真,则该元素会被发送;反之被忽略

  filter(Predicate<? super T> p)
  
  Flux<Integer> ints = Flux.range(1, 4);
  Flux<Integer> filtered = ints.filter(i -> i % 2 == 0);
buffer

将上游元素分段,当元素积累了一定数量后一并发送(组成列表,注意 buffer 后的类型 List)

  Flux<Integer> ints = Flux.range(1, 40);
  Flux<List<Integer>> buffered = ints.buffer(3);
retry

在响应式流传递过程中报错时重新订阅这个发布(在 Flux 中要注意元素重复消费的问题)

  Flux.log().retry(3);
zip

将两个响应式流合并成一个,直到其中任意一个流元素耗尽,这个是非常有用的。

  Flux<Integer> fluxA = Flux.range(1, 4);
  Flux<Integer> fluxB = Flux.range(5, 5);
  fluxA.zipWith(fluxB, (a, b)-> a+b)
其他
  • cast 对元素进行强制类型转换
  • Flux#index 对元素在流中的位置下标进行注明(从0开始),返回 Tuple2<Long, T>类型的Flux。
  • flatMap 将元素进行1对多的映射,可以是异步的方法调用(map只能是同步映射)
  • Flux#startWith 在元素序列开头添加元素
  • Flux#concatWithValues 在元素序列结尾添加元素
  • Flux#collectList 将Flux聚合成一个List
  • Flux#collectMap 将Flux聚合成一个Map
  • Flux#count 计算序列的大小
  • Flux#reduce 对相邻元素进行计算(归约)
  • Flux#take 取一个序列从头开始的n个元素
  • Flux#takeLast 取一个序列最后的的n个元素
  • Flux#skip 跳过n个元素
  • Flux#takeUntil 取元素直到满足条件(类似repeat until循环)
  • Flux#takeWhile 当满足条件时取元素(类似while循环)

观察Mono/Flux

这里的观察是指对序列进行观察且不会改变其中元素的状态

  • doOnNext 在序列向下游传送onNext时进行调用
  • doOnComplete 在序列向下游传送onComplete时进行调用
  • doOnError 在序列向下游传送onError时进行调用
  • doOnCancel 在Subscription.cancel时执行该回调(先于cancel信号向上游发送前执行)
  • doFirst 在序列开始前执行
  • doOnSubscribe 在Subscription开始后,它比doFirst执行要晚
  • doOnRequest 在Flux/Mono接收到(请求元素)request时调用(先于request信号向上游发送前执行)
  • doOnTerminate 在Flux/Mono结束(无论成功与否)执行(先于onComplete/onError信号向下游发送前执行)
  • doAfterTerminate 在Flux/Mono结束(无论成功与否)执行(后于onComplete/onError信号向下游发送前执行)
  • doOnEach 任何元素发送前皆会执行(onComplete/onError/onNext)
  • doFinally Flux/Mono因为任何原因(COMPLETE/ERROR/CANCEL)终结后皆会执行
  • log 记录内部日志(常用于调试)

Hot流和Cold流

FluxMono 代表元素的异步序列,我们只有在调用subscribe方法时才会对其中元素进行处理;

但实际上,根据他们产生元素的条件,我们可以将Publisher划分成两类:

  • Cold 每次订阅都会生成新的数据,如果没有订阅,那么元素不会被生成。
  • Hot 即使在没有订阅者的情况下也会生成元素,他们会持续向下游发送数据,订阅者只能观察到注册订阅后的元素。

这种 Hot(实时流)和 Cold(非实时流)的划分,可以更精确的描述现实中元素产生的场景。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Project Reactor 是一个基于反应式流规范的库,用于构建异步、非阻塞的应用程序。下面是 Project Reactor 常用API: 1. Flux:Flux 是 Project Reactor 中最基本的类型之一,它代表一个可订阅的异步序列,可以发射零到多个元素,用于表示一个数据流。 2. Mono:Mono 也是 Project Reactor 中的基本类型之一,它表示异步的结果或一个可能为空的值。 3. Schedulers:Schedulers 是用于处理异步任务的调度器的工具类。它提供了一些方法,例如在不同的线程池中执行任务、延迟执行任务等。 4. Flux/ Mono 的操作符:Project Reactor 提供了丰富的操作符,用于对流进行变换、过滤、组合和聚合等操作。例如 map、flatMap、filter、reduce 等。 5. 静态工厂方法:Project Reactor 提供了一些静态工厂方法,用于创建 Flux 或 Mono。例如 just、fromIterable、empty、error 等。 6. 错误处理:Project Reactor 提供了一些操作符,用于处理流中的错误,例如 onErrorReturn、onErrorResume、retry 等。 7. 条件操作符:Project Reactor 提供了一些条件操作符,例如 takeWhile、skipUntil、timeout 等,用于根据条件决定是否终止流或跳过某些元素。 8. Hot/Cold 发布者:Project Reactor 中的 Flux 和 Mono 可以分别被视为热发布者(Hot Publisher)和冷发布者(Cold Publisher)。热发布者在订阅之前已经开始发射元素,而冷发布者只在订阅时开始发射元素。 总结来说,Project Reactor常用 API 主要包括 Flux 和 Mono 类型,Schedulers 调度器,操作符,静态工厂方法以及错误处理和条件操作符等。这些 API 提供了丰富的功能和灵活性,使得开发者能够方便地构建异步、非阻塞的应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔道不误砍柴功

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值