reactor.core 类基本讲解
一、接口
1.1、SynchronousSink接口
一次处理一批或者一个,代表着同步
sync 代表同步 async 代表异步; sink调用、渗透、消失的含义
Subscriber—订阅者 Consumer–消费者 Producer 生产者 Publisher 发布者
生产者-服务器-需要传递数据过来有,无参数,有return,给数据的勾当;消费者–客户端(个人用户)-需要接收参数(或者消息),无return ,有参数,看数据,用数据的勾当。
订阅发布者模式本质上也是一种生产者消费者模式,订阅者是消费者-(个人),发布者是生产者-(服务器)。如果一定要说个区别,就是抽象级别的区别吧
emit-- 发出,放射;发行;发表 ,把消息搞出去
这个接口有四个方法:
void complete();
Context currentContext(); 返回当前订阅者,就是个人
void error(Throwable e);
void next(T t);
解释:
接口以同步地向底层订阅者产生“一个信号”。
每次调用生成器函数最多调用一个next(T)调用 and/or 一个complete()或error(Throwable)调 在生成函数被调用之前需要被调用。
禁止在生成器使用者或函数外部调用SynchronousSink,例如使用异步回调。对于这些情况,您可以使用基于FluxSink或MonoSink的生成器。
1.2、FluxSink接口
异步的源源不断地调用,流水管道一样
void complete();
Context currentContext();
void error(Throwable e);
FluxSink<T> next(T t);
long requestedFromDownstream();
boolean isCancelled();
FluxSink<T> onRequest(LongConsumer consumer);
FluxSink<T> onCancel(Disposable d);
FluxSink<T> onDispose(Disposable d);
enum OverflowStrategy {
IGNORE,
ERROR,
DROP,
LATEST,
BUFFER
}
FluxSink支持发送多个元素给下游消费者,且内置多种队列作为数据缓冲存储可以在初始化时指定存储队列。
OverflowStrategy.BUFFER使用的是一个无界队列,需要额外注意OOM(内存溢出)问题
fluxSink这里看是无限循环next产生数据,实则不用担心,如果subscribe与fluxSink都是同一个线程的话(本实例都是在main线程
),它们是同步阻塞调用的。
subscribe的时候调用LambdaSubscriber.onSubscribe,request(N)请求数据,然后再调用source.accept,也就是调用fluxSink的lambda方法产生数据,开启stream模式
这里的fluxSink.next里头阻塞调用了subscribe的consumer,返回之后才继续循环。
至于BUFFER模式OOM的问题,可以思考下如何产生。
二、利用builder(建造者模式)中会使用很多个方法:
操作符
2.1、zipWith
zipWith 操作符把当前流中的元素与另外一个流中的元素按照一对一的方式进行合并。在合并时可以不做任何处理,由此得到的是一个元素类型为 Tuple2 的流;也可以通过一个 BiFunction 函数对合并的元素进行处理,所得到的流的元素类型为该函数的返回值。
包含两个值组成一个元素,包含0-N个元素的一个流
在代码清单 8 中,两个流中包含的元素分别是 a,b 和 c,d。第一个 zipWith 操作符没有使用合并函数,因此结果流中的元素类型为 Tuple2;第二个 zipWith 操作通过合并函数把元素类型变为 String。
清单 8. zipWith 操作符使用示例
Flux.just("a","b","100","200").zipWith(Flux.just("1","2","3")).subscribe(System.out::println);
Flux.just("a", "b")
.zipWith(Flux.just("c", "d"), (s1, s2) -> String.format("%s-%s", s1, s2))
.subscribe(System.out::println);
结果
15:15:43.010 [main] DEBUG reactor.util.Loggers$LoggerFactory - Using Slf4j logging framework
[a,1]
[b,2]
[100,3]
2.2、doOnNext
doOnNext是观察者被通知之前(也就是回调之前)会调用的方法,说白了就是最终回调之前的前一个回调方法,这个方法一般做的事件类似于观察者做的事情,只是自己不是最终的回调者。(观察者即最终回调者)
干的事情倒数第二步
2.3、doOnSubscribe
doOnSubscribe是事件被订阅之前(也就是事件源发起之前)会调用的方法,这个方法一般用于修改、添加或者删除事件源的数据流。
2.4、filter
对流中包含的元素进行过滤,只留下满足 Predicate 指定条件的元素。代码清单 6 中的语句输出的是 1 到 10 中的所有偶数。
清单 6. filter 操作符使用示例
Flux.range(1, 10).filter(i -> i % 2 == 0).subscribe(System.out::println);
2.5、buffer 和 bufferTimeout
这两个操作符的作用是把当前流中的元素收集到集合中,并把集合对象作为流中的新元素。在进行收集时可以指定不同的条件:所包含的元素的最大数量或收集的时间间隔。方法 buffer()仅使用一个条件,而 bufferTimeout()可以同时指定两个条件。指定时间间隔时可以使用 Duration 对象或毫秒数,即使用 bufferMillis()或 bufferTimeoutMillis()两个方法。
2.6、window
window 操作符的作用类似于 buffer,所不同的是 window 操作符是把当前流中的元素收集到另外的 Flux 序列中,因此返回值类型是 Flux。在代码清单 7 中,两行语句的输出结果分别是 5 个和 2 个 UnicastProcessor 字符。这是因为 window 操作符所产生的流中包含的是 UnicastProcessor 类的对象,而 UnicastProcessor 类的 toString 方法输出的就是 UnicastProcessor 字符。
清单 7. window 操作符使用示例
Flux.range(1, 100).window(20).subscribe(System.out::println);
Flux.intervalMillis(100).windowMillis(1001).take(2).toStream().forEach(System.out::println)
2.7、take
take 系列操作符用来从当前流中提取元素。提取的方式可以有很多种。
- take(long n),take(Duration timespan)和 takeMillis(long timespan):按照指定的数量或时间间隔来提取。
- takeLast(long n):提取流中的最后 N 个元素。
- takeUntil(Predicate<? super T> predicate):提取元素直到 Predicate 返回 true。
- takeWhile(Predicate<? super T> continuePredicate): 当 Predicate 返回 true 时才进行提取。
- takeUntilOther(Publisher<?> other):提取元素直到另外一个流开始产生元素。
在代码清单 9 中,第一行语句输出的是数字 1 到 10;第二行语句输出的是数字 991 到 1000;第三行语句输出的是数字 1 到 9;第四行语句输出的是数字 1 到 10,使得 Predicate 返回 true 的元素也是包含在内的。
清单 9. take 系列操作符使用示例
Flux.range(1, 1000).take(10).subscribe(System.out::println);
Flux.range(1, 1000).takeLast(10).subscribe(System.out::println);
Flux.range(1, 1000).takeWhile(i -> i < 10).subscribe(System.out::println);
Flux.range(1, 1000).takeUntil(i -> i == 10).subscribe(System.out::println);
2.8、reduce 和 reduceWith (多变少)
reduce 和 reduceWith 操作符对流中包含的所有元素进行累积操作,得到一个包含计算结果的 Mono 序列。累积操作是通过一个 BiFunction 来表示的。在操作时可以指定一个初始值。如果没有初始值,则序列的第一个元素作为初始值。
在代码清单 10 中,第一行语句对流中的元素进行相加操作,结果为 5050;第二行语句同样也是进行相加操作,不过通过一个 Supplier 给出了初始值为 100,所以结果为 5150。
清单 10. reduce 和 reduceWith 操作符使用示例
Flux.range(1, 100).reduce((x, y) -> x + y).subscribe(System.out::println);
Flux.range(1, 100).reduceWith(() -> 100, (x, y) -> x + y).subscribe(System.out::println)
2.8、merge 和 mergeSequential (少变多)
merge 和 mergeSequential 操作符用来把多个流合并成一个 Flux 序列。不同之处在于 merge 按照所有流中元素的实际产生顺序来合并,而 mergeSequential 则按照所有流被订阅的顺序,以流为单位进行合并。
代码清单 11 中分别使用了 merge 和 mergeSequential 操作符。进行合并的流都是每隔 100 毫秒产生一个元素,不过第二个流中的每个元素的产生都比第一个流要延迟 50 毫秒。在使用 merge 的结果流中,来自两个流的元素是按照时间顺序交织在一起;而使用 mergeSequential 的结果流则是首先产生第一个流中的全部元素,再产生第二个流中的全部元素。
清单 11. merge 和 mergeSequential 操作符使用示例
Flux.merge(Flux.intervalMillis(0, 100).take(5), Flux.intervalMillis(50, 100).take(5))
.toStream()
.forEach(System.out::println);
Flux.mergeSequential(Flux.intervalMillis(0, 100).take(5), Flux.intervalMillis(50, 100).take(5))
.toStream()
.forEach(System.out::println);
2.9、flatMap 和 flatMapSequential
flatMap 和 flatMapSequential 操作符把流中的每个元素转换成一个流,再把所有流中的元素进行合并。flatMapSequential 和 flatMap 之间的区别与 mergeSequential 和 merge 之间的区别是一样的。
在代码清单 12 中,流中的元素被转换成每隔 100 毫秒产生的数量不同的流,再进行合并。由于第一个流中包含的元素数量较少,所以在结果流中一开始是两个流的元素交织在一起,然后就只有第二个流中的元素。
清单 12. flatMap 操作符使用示例
Flux.just(5, 10)
.flatMap(x -> Flux.intervalMillis(x * 10, 100).take(x))
.toStream()
.forEach(System.out::println);
2.10、concatMap
concatMap 操作符的作用也是把流中的每个元素转换成一个流,再把所有流进行合并。与 flatMap 不同的是,concatMap 会根据原始流中的元素顺序依次把转换之后的流进行合并;与 flatMapSequential 不同的是,concatMap 对转换之后的流的订阅是动态进行的,而 flatMapSequential 在合并之前就已经订阅了所有的流。
代码清单 13 与代码清单 12 类似,只不过把 flatMap 换成了 concatMap,结果流中依次包含了第一个流和第二个流中的全部元素。
清单 13. concatMap 操作符使用示例
Flux.just(5, 10)
.concatMap(x -> Flux.intervalMillis(x * 10, 100).take(x))
.toStream()
.forEach(System.out::println);
2.11、combineLatest
combineLatest 操作符把所有流中的最新产生的元素合并成一个新的元素,作为返回结果流中的元素。只要其中任何一个流中产生了新的元素,合并操作就会被执行一次,结果流中就会产生新的元素。在 代码清单 14 中,流中最新产生的元素会被收集到一个数组中,通过 Arrays.toString 方法来把数组转换成 String。
清单 14. combineLatest 操作符使用示例
Flux.combineLatest(
Arrays::toString,
Flux.intervalMillis(100).take(5),
Flux.intervalMillis(50, 100).take(5)
).toStream().forEach(System.out::println);
2.12、
三、消息处理
当需要处理 Flux 或 Mono 中的消息时,如之前的代码清单所示,可以通过 subscribe 方法来添加相应的订阅逻辑。在调用 subscribe 方法时可以指定需要处理的消息类型。可以只处理其中包含的正常消息,也可以同时处理错误消息和完成消息。代码清单 15 中通过 subscribe()方法同时处理了正常消息和错误消息。
通过 subscribe()方法处理正常和错误消息
Flux.just(1, 2)
.concatWith(Mono.error(new IllegalStateException()))
.subscribe(System.out::println, System.err::println);
出现错误时返回默认值
Flux.just(1, 2)
.concatWith(Mono.error(new IllegalStateException()))
.onErrorReturn(0)
.subscribe(System.out::println);
出现错误时根据异常类型来选择流
Flux.just(1, 2)
.concatWith(Mono.error(new IllegalArgumentException()))
.onErrorResumeWith(e -> {
if (e instanceof IllegalStateException) {
return Mono.just(0);
} else if (e instanceof IllegalArgumentException) {
return Mono.just(-1);
}
return Mono.empty();
})
.subscribe(System.out::println);
当出现错误时,还可以通过 retry 操作符来进行重试。重试的动作是通过重新订阅序列来实现的。在使用 retry 操作符时可以指定重试的次数。代码清单 19 中指定了重试次数为 1,所输出的结果是 1,2,1,2 和错误信息。
使用 retry 操作符进行重试
Flux.just(1, 2)
.concatWith(Mono.error(new IllegalStateException()))
.retry(1)
.subscribe(System.out::println);
四、调度器
前面介绍了反应式流和在其上可以进行的各种操作,通过调度器(Scheduler)可以指定这些操作执行的方式和所在的线程。有下面几种不同的调度器实现。
-
当前线程,通过 Schedulers.immediate()方法来创建。
-
单一的可复用的线程,通过 Schedulers.single()方法来创建。
-
使用弹性的线程池,通过 Schedulers.elastic()方法来创建。线程池中的线程是可以复用的。当所需要时,新的线程会被创建。如果一个线程闲置太长时间,则会被销毁。该调度器适用于 I/O 操作相关的流的处理。
-
使用对并行操作优化的线程池,通过 Schedulers.parallel()方法来创建。其中的线程数量取决于 CPU 的核的数量。该调度器适用于计算密集型的流的处理。
-
使用支持任务调度的调度器,通过 Schedulers.timer()方法来创建。
-
从已有的 ExecutorService 对象中创建调度器,通过 Schedulers.fromExecutorService()方法来创建。
使用 create()方法创建一个新的 Flux 对象,其中包含唯一的元素是当前线程的名称。接着是两对 publishOn()和 map()方法,其作用是先切换执行时的调度器,再把当前的线程名称作为前缀添加。最后通过 subscribeOn()方法来改变流产生时的执行方式。运行之后的结果是[elastic-2] [single-1] parallel-1。最内层的线程名字 parallel-1 来自产生流中元素时使用的 Schedulers.parallel()调度器,中间的线程名称 single-1 来自第一个 map 操作之前的 Schedulers.single()调度器,最外层的线程名字 elastic-2 来自第二个 map 操作之前的 Schedulers.elastic()调度器。
Flux.create(sink -> {
sink.next(Thread.currentThread().getName());
sink.complete();
})
.publishOn(Schedulers.single())
.map(x -> String.format("[%s] %s", Thread.currentThread().getName(), x))
.publishOn(Schedulers.elastic())
.map(x -> String.format("[%s] %s", Thread.currentThread().getName(), x))
.subscribeOn(Schedulers.parallel())
.toStream()
.forEach(System.out::println);
调度器与线程模型
在Reactor中,对于多线程并发调度的处理变得异常简单。
在以往的多线程开发场景中,我们通常使用Executors
工具类来创建线程池,通常有如下四种类型:
newCachedThreadPool
创建一个弹性大小缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程;newFixedThreadPool
创建一个大小固定的线程池,可控制线程最大并发数,超出的线程会在队列中等待;newScheduledThreadPool
创建一个大小固定的线程池,支持定时及周期性的任务执行;newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
此外,newWorkStealingPool
还可以创建支持work-stealing的线程池。
说良心话,Java提供的Executors
工具类使得我们对ExecutorService
使用已经非常得心应手了。BUT~ Reactor让线程管理和任务调度更加“傻瓜”——调度器(Scheduler)帮助我们搞定这件事。Scheduler
是一个拥有多个实现类的抽象接口。Schedulers
类(按照通常的套路,最后为s
的就是工具类咯)提供的静态方法可搭建以下几种线程执行环境:
- 当前线程(
Schedulers.immediate()
); - 可重用的单线程(
Schedulers.single()
)。注意,这个方法对所有调用者都提供同一个线程来使用, 直到该调度器被废弃。如果你想使用独占的线程,请使用Schedulers.newSingle()
; - 弹性线程池(
Schedulers.elastic()
)。它根据需要创建一个线程池,重用空闲线程。线程池如果空闲时间过长 (默认为 60s)就会被废弃。对于 I/O 阻塞的场景比较适用。Schedulers.elastic()
能够方便地给一个阻塞 的任务分配它自己的线程,从而不会妨碍其他任务和资源; - 固定大小线程池(
Schedulers.parallel()
),所创建线程池的大小与CPU个数等同; - 自定义线程池(
Schedulers.fromExecutorService(ExecutorService)
)基于自定义的ExecutorService创建 Scheduler(虽然不太建议,不过你也可以使用Executor来创建)。
Schedulers
类已经预先创建了几种常用的线程池:使用single()
、elastic()
和parallel()
方法可以分别使用内置的单线程、弹性线程池和固定大小线程池。如果想创建新的线程池,可以使用newSingle()
、newElastic()
和newParallel()
方法。
Executors
提供的几种线程池在Reactor中都支持:
Schedulers.single()
和Schedulers.newSingle()
对应Executors.newSingleThreadExecutor()
;Schedulers.elastic()
和Schedulers.newElastic()
对应Executors.newCachedThreadPool()
;Schedulers.parallel()
和Schedulers.newParallel()
对应Executors.newFixedThreadPool()
;- 下一章会介绍到,
Schedulers
提供的以上三种调度器底层都是基于ScheduledExecutorService
的,因此都是支持任务定时和周期性执行的; Flux
和Mono
的调度操作符subscribeOn
和publishOn
支持work-stealing。
举例:将同步的阻塞调用变为异步的
前面介绍到Schedulers.elastic()
能够方便地给一个阻塞的任务分配专门的线程,从而不会妨碍其他任务和资源。我们就可以利用这一点将一个同步阻塞的调用调度到一个自己的线程中,并利用订阅机制,待调用结束后异步返回。
假设我们有一个同步阻塞的调用方法:
private String getStringSync() {
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, Reactor!";
}
12345678
正常情况下,调用这个方法会被阻塞2秒钟,然后同步地返回结果。我们借助elastic调度器将其变为异步,由于是异步的,为了保证测试方法所在的线程能够等待结果的返回,我们使用CountDownLatch
:
@Test
public void testSyncToAsync() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
Mono.fromCallable(() -> getStringSync()) // 1
.subscribeOn(Schedulers.elastic()) // 2
.subscribe(System.out::println, null, countDownLatch::countDown);
countDownLatch.await(10, TimeUnit.SECONDS);
}
12345678
- 使用
fromCallable
声明一个基于Callable的Mono; - 使用
subscribeOn
将任务调度到Schedulers
内置的弹性线程池执行,弹性线程池会为Callable的执行任务分配一个单独的线程。
切换调度器的操作符
Reactor 提供了两种在响应式链中调整调度器 Scheduler的方法:publishOn
和subscribeOn
。它们都接受一个 Scheduler
作为参数,从而可以改变调度器。但是publishOn
在链中出现的位置是有讲究的,而subscribeOn
则无所谓。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3fGPBOlS-1627260219318)(https://leanote.com/api/file/getImage?fileId=5a918429ab64414490001821)]
假设与上图对应的代码是:
Flux.range(1, 1000)
.map(…)
.publishOn(Schedulers.elastic()).filter(…)
.publishOn(Schedulers.parallel()).flatMap(…)
.subscribeOn(Schedulers.single())
- 如图所示,
publishOn
会影响链中其后的操作符,比如第一个publishOn调整调度器为elastic,则filter
的处理操作是在弹性线程池中执行的;同理,flatMap
是执行在固定大小的parallel线程池中的; subscribeOn
无论出现在什么位置,都只影响源头的执行环境,也就是range
方法是执行在单线程中的,直至被第一个publishOn
切换调度器之前,所以range
后的map
也在单线程中执行。
springboot webflux mono 使用说明
*相关类与接口*
*Mono:**包含0或者1个元素*
public abstract class Mono<T> implements CorePublisher<T> {
static final BiPredicate EQUALS_BIPREDICATE = Object::equals;
public Mono() {
}
public static <T> Mono<T> create(Consumer<MonoSink<T>> callback) { //创建Mono对象
public static Mono<Long> delay(Duration duration) {
public static Mono<Long> delay(Duration duration, Scheduler timer) {
public static <T> Mono<T> empty() { //内容为空,订阅时执行Operators.complete操作
return MonoEmpty.instance();
}
public static <T> Mono<T> never() { //内容为空,订阅时不执行任何操作
return MonoNever.instance();
}
public static <T> Mono<T> error(Throwable error) {
public static <T> Mono<T> error(Supplier<? extends Throwable> errorSupplier) {
@SafeVarargs
public static <T> Mono<T> first(Mono<? extends T>... monos) {
public static <T> Mono<T> first(Iterable<? extends Mono<? extends T>> monos) {
static <T> Mono<Void> empty(Publisher<T> source) { //方法权限default,只能在同一个包中调用
Mono<Void> then = ignoreElements(source);
return then;
}
public static <T> Mono<T> ignoreElements(Publisher<T> source) {
public static Mono<Context> subscriberContext() {
***************
just 操作:立刻创建Mono对象
public static <T> Mono<T> just(T data) { //创建不为空的Mono对象
public static <T> Mono<T> justOrEmpty(@Nullable Optional<? extends T> data) {
public static <T> Mono<T> justOrEmpty(@Nullable T data) { //创建包含0或者1个元素的对象
***************
defer 操作:延时创建Mono对象,当subscribe方法调用时,才会创建对象
public static <T> Mono<T> defer(Supplier<? extends Mono<? extends T>> supplier) {
public static <T> Mono<T> deferWithContext(Function<Context, ? extends Mono<? extends T>> supplier) {
***************
from 操作
public static <T> Mono<T> from(Publisher<? extends T> source) {
public static <I> Mono<I> fromDirect(Publisher<? extends I> source) {
public static <T> Mono<T> fromSupplier(Supplier<? extends T> supplier) {
public static <T> Mono<T> fromRunnable(Runnable runnable) {
public static <T> Mono<T> fromCallable(Callable<? extends T> supplier) {
public static <T> Mono<T> fromCompletionStage(CompletionStage<? extends T> completionStage) {
public static <T> Mono<T> fromCompletionStage(Supplier<? extends CompletionStage<? extends T>> stageSupplier) {
public static <T> Mono<T> fromFuture(CompletableFuture<? extends T> future) {
public static <T> Mono<T> fromFuture(Supplier<? extends CompletableFuture<? extends T>> futureSupplier) {
***************
sequenceEqual 操作:比较对象流是否相等
public static <T> Mono<Boolean> sequenceEqual(Publisher<? extends T> source1, Publisher<? extends T> source2) {
public static <T> Mono<Boolean> sequenceEqual(Publisher<? extends T> source1, Publisher<? extends T> source2, BiPredicate<? super T, ? super T> isEqual) {
public static <T> Mono<Boolean> sequenceEqual(Publisher<? extends T> source1, Publisher<? extends T> source2, BiPredicate<? super T, ? super T> isEqual, int prefetch) {
***************
using 操作
public static <T, D> Mono<T> using(Callable<? extends D> resourceSupplier, Function<? super D, ? extends Mono<? extends T>> sourceSupplier, Consumer<? super D> resourceCleanup, boolean eager) {
//callable返回初始的数据源,function对初始的数据源进行操作
//consumer执行清理操作
//eager为true(默认):consumer在subscribe之前调用
//eager为false:consumer在subscribe之后调用
public static <T, D> Mono<T> using(Callable<? extends D> resourceSupplier, Function<? super D, ? extends Mono<? extends T>> sourceSupplier, Consumer<? super D> resourceCleanup) {
return using(resourceSupplier, sourceSupplier, resourceCleanup, true);
} //consumer操作默认在subscribe之前调用
public static <T, D> Mono<T> usingWhen(Publisher<D> resourceSupplier, Function<? super D, ? extends Mono<? extends T>> resourceClosure, Function<? super D, ? extends Publisher<?>> asyncCleanup) {
public static <T, D> Mono<T> usingWhen(Publisher<D> resourceSupplier, Function<? super D, ? extends Mono<? extends T>> resourceClosure, Function<? super D, ? extends Publisher<?>> asyncComplete, BiFunction<? super D, ? super Throwable, ? extends Publisher<?>> asyncError, Function<? super D, ? extends Publisher<?>> asyncCancel) {
***************
when 操作:当被调用的时候执行预设的操作
public static Mono<Void> when(Publisher<?>... sources) {
public static Mono<Void> when(Iterable<? extends Publisher<?>> sources) {
public static Mono<Void> whenDelayError(Iterable<? extends Publisher<?>> sources) {
public static Mono<Void> whenDelayError(Publisher<?>... sources) {
***************
zip 操作:压缩对象流
public static <T1, T2> Mono<Tuple2<T1, T2>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2) {
public static <T1, T2, O> Mono<O> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, BiFunction<? super T1, ? super T2, ? extends O> combinator) {
public static <T1, T2, T3> Mono<Tuple3<T1, T2, T3>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3) {
public static <T1, T2, T3, T4> Mono<Tuple4<T1, T2, T3, T4>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4) {
public static <T1, T2, T3, T4, T5> Mono<Tuple5<T1, T2, T3, T4, T5>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5) {
public static <T1, T2, T3, T4, T5, T6> Mono<Tuple6<T1, T2, T3, T4, T5, T6>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6) {
public static <T1, T2, T3, T4, T5, T6, T7> Mono<Tuple7<T1, T2, T3, T4, T5, T6, T7>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6, Mono<? extends T7> p7) {
public static <T1, T2, T3, T4, T5, T6, T7, T8> Mono<Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>> zip(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6, Mono<? extends T7> p7, Mono<? extends T8> p8) {
public static <R> Mono<R> zip(Iterable<? extends Mono<?>> monos, Function<? super Object[], ? extends R> combinator) {
public static <R> Mono<R> zip(Function<? super Object[], ? extends R> combinator, Mono<?>... monos) {
public static <T1, T2> Mono<Tuple2<T1, T2>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2) {
public static <T1, T2, T3> Mono<Tuple3<T1, T2, T3>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3) {
public static <T1, T2, T3, T4> Mono<Tuple4<T1, T2, T3, T4>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4) {
public static <T1, T2, T3, T4, T5> Mono<Tuple5<T1, T2, T3, T4, T5>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5) {
public static <T1, T2, T3, T4, T5, T6> Mono<Tuple6<T1, T2, T3, T4, T5, T6>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6) {
public static <T1, T2, T3, T4, T5, T6, T7> Mono<Tuple7<T1, T2, T3, T4, T5, T6, T7>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6, Mono<? extends T7> p7) {
public static <T1, T2, T3, T4, T5, T6, T7, T8> Mono<Tuple8<T1, T2, T3, T4, T5, T6, T7, T8>> zipDelayError(Mono<? extends T1> p1, Mono<? extends T2> p2, Mono<? extends T3> p3, Mono<? extends T4> p4, Mono<? extends T5> p5, Mono<? extends T6> p6, Mono<? extends T7> p7, Mono<? extends T8> p8) {
public static <R> Mono<R> zipDelayError(Iterable<? extends Mono<?>> monos, Function<? super Object[], ? extends R> combinator) {
public static <R> Mono<R> zipDelayError(Function<? super Object[], ? extends R> combinator, Mono<?>... monos) {
***************
flatMap 操作
public final <R> Mono<R> flatMap(Function<? super T, ? extends Mono<? extends R>> transformer) {
public final <R> Flux<R> flatMapMany(Function<? super T, ? extends Publisher<? extends R>> mapper) {
public final <R> Flux<R> flatMapMany(Function<? super T, ? extends Publisher<? extends R>> mapperOnNext, Function<? super Throwable, ? extends Publisher<? extends R>> mapperOnError, Supplier<? extends Publisher<? extends R>> mapperOnComplete) {
public final <R> Flux<R> flatMapIterable(Function<? super T, ? extends Iterable<? extends R>> mapper) {
***************
map 操作
public final <R> Mono<R> map(Function<? super T, ? extends R> mapper) {
***************
transform 操作
public final <V> Mono<V> transform(Function<? super Mono<T>, ? extends Publisher<V>> transformer) {
public final <V> Mono<V> transformDeferred(Function<? super Mono<T>, ? extends Publisher<V>> transformer) {
***************
filter 操作
public final Mono<T> filter(Predicate<? super T> tester) {
public final Mono<T> filterWhen(Function<? super T, ? extends Publisher<Boolean>> asyncPredicate) {
***************
do 操作
public final Mono<T> doFirst(Runnable onFirst) {
public final Mono<T> doFinally(Consumer<SignalType> onFinally) {
public final Mono<T> doOnCancel(Runnable onCancel) {
public final <R> Mono<T> doOnDiscard(Class<R> type, Consumer<? super R> discardHook) {
public final Mono<T> doOnNext(Consumer<? super T> onNext) {
public final Mono<T> doOnSuccess(Consumer<? super T> onSuccess) {
public final Mono<T> doOnEach(Consumer<? super Signal<T>> signalConsumer) {
public final Mono<T> doOnError(Consumer<? super Throwable> onError) {
public final <E extends Throwable> Mono<T> doOnError(Class<E> exceptionType, Consumer<? super E> onError) {
public final Mono<T> doOnError(Predicate<? super Throwable> predicate, Consumer<? super Throwable> onError) {
public final Mono<T> doOnRequest(LongConsumer consumer) {
public final Mono<T> doOnSubscribe(Consumer<? super Subscription> onSubscribe) {
public final Mono<T> doOnTerminate(Runnable onTerminate) {
public final Mono<T> doAfterTerminate(Runnable afterTerminate) {
***************
block 操作
@Nullable
public T block() {
@Nullable
public T block(Duration timeout) {
public Optional<T> blockOptional() {
public Optional<T> blockOptional(Duration timeout) {
***************
cache 操作
public final Mono<T> cache() {
public final Mono<T> cache(Duration ttl) {
public final Mono<T> cache(Duration ttl, Scheduler timer) {
public final Mono<T> cache(Function<? super T, Duration> ttlForValue, Function<Throwable, Duration> ttlForError, Supplier<Duration> ttlForEmpty) {
***************
checkpoint 操作
public final Mono<T> checkpoint() {
public final Mono<T> checkpoint(String description) {
public final Mono<T> checkpoint(@Nullable String description, boolean forceStackTrace) {
***************
delay 操作
public final Mono<T> delayElement(Duration delay) {
public final Mono<T> delayElement(Duration delay, Scheduler timer) {
public final Mono<T> delayUntil(Function<? super T, ? extends Publisher<?>> triggerProvider) {
public final Mono<T> delaySubscription(Duration delay) {
public final Mono<T> delaySubscription(Duration delay, Scheduler timer) {
public final <U> Mono<T> delaySubscription(Publisher<U> subscriptionDelay) {
***************
elapsed 操作
public final Mono<Tuple2<Long, T>> elapsed() {
public final Mono<Tuple2<Long, T>> elapsed(Scheduler scheduler) {
***************
expand 操作
public final Flux<T> expandDeep(Function<? super T, ? extends Publisher<? extends T>> expander, int capacityHint) {
public final Flux<T> expandDeep(Function<? super T, ? extends Publisher<? extends T>> expander) {
public final Flux<T> expand(Function<? super T, ? extends Publisher<? extends T>> expander, int capacityHint) {
public final Flux<T> expand(Function<? super T, ? extends Publisher<? extends T>> expander) {
***************
log 操作
public final Mono<T> log() {
return this.log((String)null, Level.INFO);
}
public final Mono<T> log(@Nullable String category) {
return this.log(category, Level.INFO);
}
public final Mono<T> log(@Nullable String category, Level level, SignalType... options) {
return this.log(category, level, false, options);
}
public final Mono<T> log(@Nullable String category, Level level, boolean showOperatorLine, SignalType... options) {
SignalLogger<T> log = new SignalLogger(this, category, level, showOperatorLine, options);
return this instanceof Fuseable ? onAssembly(new MonoLogFuseable(this, log)) : onAssembly(new MonoLog(this, log));
}
public final Mono<T> log(Logger logger) {
return this.log(logger, Level.INFO, false);
}
public final Mono<T> log(Logger logger, Level level, boolean showOperatorLine, SignalType... options) {
***************
onError 操作
public final Mono<T> onErrorContinue(BiConsumer<Throwable, Object> errorConsumer) {
public final <E extends Throwable> Mono<T> onErrorContinue(Class<E> type, BiConsumer<Throwable, Object> errorConsumer) {
public final <E extends Throwable> Mono<T> onErrorContinue(Predicate<E> errorPredicate, BiConsumer<Throwable, Object> errorConsumer) {
public final Mono<T> onErrorStop() {
public final Mono<T> onErrorMap(Predicate<? super Throwable> predicate, Function<? super Throwable, ? extends Throwable> mapper) {
public final Mono<T> onErrorMap(Function<? super Throwable, ? extends Throwable> mapper) {
public final <E extends Throwable> Mono<T> onErrorMap(Class<E> type, Function<? super E, ? extends Throwable> mapper) {
public final Mono<T> onErrorResume(Function<? super Throwable, ? extends Mono<? extends T>> fallback) {
public final <E extends Throwable> Mono<T> onErrorResume(Class<E> type, Function<? super E, ? extends Mono<? extends T>> fallback) {
public final Mono<T> onErrorResume(Predicate<? super Throwable> predicate, Function<? super Throwable, ? extends Mono<? extends T>> fallback) {
public final Mono<T> onErrorReturn(T fallback) {
public final <E extends Throwable> Mono<T> onErrorReturn(Class<E> type, T fallbackValue) {
public final Mono<T> onErrorReturn(Predicate<? super Throwable> predicate, T fallbackValue) {
***************
publish 操作
public final <R> Mono<R> publish(Function<? super Mono<T>, ? extends Mono<? extends R>> transform) {
public final Mono<T> publishOn(Scheduler scheduler) {
***************
repeat 操作
public final Flux<T> repeat() {
public final Flux<T> repeat(BooleanSupplier predicate) {
public final Flux<T> repeat(long numRepeat) {
public final Flux<T> repeat(long numRepeat, BooleanSupplier predicate) {
public final Flux<T> repeatWhen(Function<Flux<Long>, ? extends Publisher<?>> repeatFactory) {
public final Mono<T> repeatWhenEmpty(Function<Flux<Long>, ? extends Publisher<?>> repeatFactory) {
public final Mono<T> repeatWhenEmpty(int maxRepeat, Function<Flux<Long>, ? extends Publisher<?>> repeatFactory) {
***************
retry 操作
public final Mono<T> retry() {
return this.retry(9223372036854775807L);
}
public final Mono<T> retry(long numRetries) {
return onAssembly(new MonoRetry(this, numRetries));
}
public final Mono<T> retryWhen(Retry retrySpec) {
return onAssembly(new MonoRetryWhen(this, retrySpec));
}
***************
take 操作
public final Mono<T> take(Duration duration) {
public final Mono<T> take(Duration duration, Scheduler timer) {
public final Mono<T> takeUntilOther(Publisher<?> other) {
***************
then 操作
public final Mono<Void> then() {
public final <V> Mono<V> then(Mono<V> other) {
public final <V> Mono<V> thenReturn(V value) {
public final Mono<Void> thenEmpty(Publisher<Void> other) {
public final <V> Flux<V> thenMany(Publisher<V> other) {
***************
timeout 操作
public final Mono<T> timeout(Duration timeout) {
public final Mono<T> timeout(Duration timeout, Mono<? extends T> fallback) {
public final Mono<T> timeout(Duration timeout, Scheduler timer) {
public final Mono<T> timeout(Duration timeout, @Nullable Mono<? extends T> fallback, Scheduler timer) {
public final <U> Mono<T> timeout(Publisher<U> firstTimeout) {
public final <U> Mono<T> timeout(Publisher<U> firstTimeout, Mono<? extends T> fallback) {
***************
timestamp 操作
public final Mono<Tuple2<Long, T>> timestamp() {
public final Mono<Tuple2<Long, T>> timestamp(Scheduler scheduler) {
***************
zipwhen、zipwith 操作
public final <T2> Mono<Tuple2<T, T2>> zipWhen(Function<T, Mono<? extends T2>> rightGenerator) {
public final <T2, O> Mono<O> zipWhen(Function<T, Mono<? extends T2>> rightGenerator, BiFunction<T, T2, O> combinator) {
public final <T2> Mono<Tuple2<T, T2>> zipWith(Mono<? extends T2> other) {
public final <T2, O> Mono<O> zipWith(Mono<? extends T2> other, BiFunction<? super T, ? super T2, ? extends O> combinator) {
***************
subscribe 操作
public final Disposable subscribe() {
public final Disposable subscribe(Consumer<? super T> consumer) {
public final Disposable subscribe(@Nullable Consumer<? super T> consumer, Consumer<? super Throwable> errorConsumer) {
public final Disposable subscribe(@Nullable Consumer<? super T> consumer, @Nullable Consumer<? super Throwable> errorConsumer, @Nullable Runnable completeConsumer) {
public final Disposable subscribe(@Nullable Consumer<? super T> consumer, @Nullable Consumer<? super Throwable> errorConsumer, @Nullable Runnable completeConsumer, @Nullable Consumer<? super Subscription> subscriptionConsumer) {
public final Disposable subscribe(@Nullable Consumer<? super T> consumer, @Nullable Consumer<? super Throwable> errorConsumer, @Nullable Runnable completeConsumer, @Nullable Context initialContext) {
public final void subscribe(Subscriber<? super T> actual) {
public abstract void subscribe(CoreSubscriber<? super T> var1);
public final Mono<T> subscriberContext(Context mergeContext) {
public final Mono<T> subscriberContext(Function<Context, Context> doOnContext) {
public final Mono<T> subscribeOn(Scheduler scheduler) {
public final <E extends Subscriber<? super T>> E subscribeWith(E subscriber) {
***************
其他操作
public final Mono<T> ignoreElement() { //忽略Mono内容
public final Mono<Boolean> hasElement() { //判断是否含有元素
public final Mono<T> defaultIfEmpty(T defaultV) { //如果当前对象为空,设置默认的zhidefaultValue
public final Mono<T> switchIfEmpty(Mono<? extends T> alternate) { //当前对象为空,返回新的Mono对象 alternate
public final Flux<T> flux() { //将Mono对象转换为 flux对象
public final CompletableFuture<T> toFuture() { //转换为CompleteableFuture对象
public final MonoProcessor<T> toProcessor() { //转换为MonoProcessor
public final Flux<T> concatWith(Publisher<? extends T> other) { //拼接,返回Flux对象
public final Flux<T> mergeWith(Publisher<? extends T> other) { //合并,返回Flux对象
public final <E> Mono<E> cast(Class<E> clazz) { //将存储元素转换为指定的类型E
public final <U> Mono<U> ofType(Class<U> clazz) {
Objects.requireNonNull(clazz, "clazz");
return this.filter((o) -> {
return clazz.isAssignableFrom(o.getClass());
}).cast(clazz);
}
public final Mono<Void> and(Publisher<?> other) {
if (this instanceof MonoWhen) {
MonoWhen o = (MonoWhen)this;
Mono<Void> result = o.whenAdditionalSource(other);
if (result != null) {
return result;
}
}
return when(this, other);
}
public final Mono<T> or(Mono<? extends T> other) {
if (this instanceof MonoFirst) {
MonoFirst<T> a = (MonoFirst)this;
Mono<T> result = a.orAdditionalSource(other);
if (result != null) {
return result;
}
}
return first(this, other);
}
public final Mono<T> cancelOn(Scheduler scheduler) {
public final Mono<T> name(String name) { //设置名称
public final Mono<T> tag(String key, String value) { //设置标签
public final Mono<Signal<T>> materialize() {
public final <X> Mono<X> dematerialize() {
public final Mono<T> hide() {
public final Mono<T> single() {
public final Mono<T> metrics() {
public final Mono<T> onTerminateDetach() {
public final <P> P as(Function<? super Mono<T>, P> transformer) {
public final <R> Mono<R> handle(BiConsumer<? super T, SynchronousSink<R>> handler) {
protected static <T> Mono<T> onAssembly(Mono<T> source) {
Function<Publisher, Publisher> hook = Hooks.onEachOperatorHook;
if (hook != null) {
source = (Mono)hook.apply(source);
}
if (Hooks.GLOBAL_TRACE) {
AssemblySnapshot stacktrace = new AssemblySnapshot((String)null, (Supplier)Traces.callSiteSupplierFactory.get());
source = (Mono)Hooks.addAssemblyInfo(source, stacktrace);
}
return source;
}
static <T> Mono<T> doOnSignal(Mono<T> source, @Nullable Consumer<? super Subscription> onSubscribe, @Nullable Consumer<? super T> onNext, @Nullable LongConsumer onRequest, @Nullable Runnable onCancel) {
static <T> Mono<T> doOnTerminalSignal(Mono<T> source, @Nullable Consumer<? super T> onSuccess, @Nullable Consumer<? super Throwable> onError, @Nullable BiConsumer<? super T, Throwable> onAfterTerminate) {
static <T> Mono<T> wrap(Publisher<T> source, boolean enforceMonoContract) {
static <T> BiPredicate<? super T, ? super T> equalsBiPredicate() {
public String toString()