目录
Reactor运算符决策树
创建新的序列
- 发布已经获取的T:
just
(Flux|Mono)- …T已经被包装成Optional<T>: Mono#justOrEmpty(Optional<T>)
- …T可能是null T: Mono#justOrEmpty(T)
- 从方法返回值获取
T
并作为信号返回:just
(Flux|Mono)- …懒加载 惰性获取: 使用 Mono#fromSupplier 或 将
just
(Flux|Mono) 包装在defer
(Flux|Mono)内
- …懒加载 惰性获取: 使用 Mono#fromSupplier 或 将
- 发布复数个
T
并可以明确列举: Flux#just(T…) - 可迭代的(iterable):
- 数组 Flux#fromArray
- 集合或其他实现了iterable的: Flux#fromIterable
- 一个范围内的整数: Flux#range
- 一个 Stream 作为信号的supplier: Flux#fromStream(Supplier<Stream>)
- 从各种单个值的源发布 例如:
- 一个提供者 Supplier<T>: Mono#fromSupplier
- 一个任务(Callable Runnable): Mono#fromCallable, Mono#fromRunnable
- 一个异步任务 CompletableFuture<T>: Mono#fromFuture
- 发布已经完成的:
empty
(Flux|Mono) - 发布错误信号:
error
(Flux|Mono) - 不发布任何信号的序列:
never
(Flux|Mono) - 在发布时决定:
defer
(Flux|Mono) - 取决于一次性资源(disposable resource):
using
(Flux|Mono) - 以编程的方式创建序列 (可以使用状态):
- 同步 一对一: Flux#generate
- 异步 (也可同步), 可能一次发布多个信号: Flux#create (Mono#create 同理但不能发布多个信号)
转换现有的序列
- 转换现有的数据
- 一对一的转换 (如字符串String转换为它的长度Length):
map
(Flux|Mono)- …只是类型转换:
cast
(Flux|Mono) - …要实现每个源值的索引: Flux#index
- …只是类型转换:
- 一对多的转换 (如字符串String转换为字符Character):
flatMap
(Flux|Mono) + 使用工厂方法 - 一对多转换 每个源元素或(和)状态需要程序化的行为:
handle
(Flux|Mono) - 为每个源信号运行一个异步任务 (如每个url一个http请求):
flatMap
(Flux|Mono) + 一个异步Publisher-返回方法- …忽略某些数据: 在flatMap的lanbda中按条件返回 Mono.empty()
- …保留原始序列的顺序: Flux#flatMapSequential (会立即触发异步进程,但会重新排序结果)
- …异步任务可以从Mono源返回多个值: Mono#flatMapMany
- 一对一的转换 (如字符串String转换为它的长度Length):
- 将预设的元素添加到现有的序列中
- 加在开头: Flux#startWith(T…)
- 加在结尾: Flux#concatWithValues(T…)
- 聚合一个Flux: (下面省略
Flux#
前缀 )- 聚合为List: collectList, collectSortedList
- 聚合为 Map: collectMap, collectMultiMap
- 聚合为任意容器: collect
- 聚合为序列的大小(size): count
- 通过在每个元素间调用一个函数 (如运行sum): reduce
- …但发出每个中间值: scan
- 通过断言(predicate)获取一个布尔值:
- 应用于所有值 (AND): all
- 应用于至少一个值 (OR): any
- 检验是否有任意值: hasElements (tMono有等价方法 hasElement)
- 检验是否有特定值: hasElement(T)
- 组合发布者
- 按顺序: Flux#concat 或
.concatWith(other)
(Flux|Mono)- …延迟任何错误,直到剩余的发布者被发出: Flux#concatDelayError
- …急切的订阅后续发布者(publisher): Flux#mergeSequential
- 按发布顺序 (按照信号到来并被接收的顺序): Flux#merge /
.mergeWith(other)
(Flux|Mono)- …类型不同 (转换并合并): Flux#zip / Flux#zipWith
- 通过将信号配对:
- 将两个Mono转换为元组2 Tuple2: Mono#zipWith
- 将n个Mono转换(当它们发出complete信号后): Mono#zip
- 协调他们的终止:
- 一个Mono与任意源到一个 Mono<Void>: Mono#and
- 任意n个完成的源: Mono#when
- 组合到任意容器:
- 每次各方都发布: Flux#zip (up to the smallest cardinality)
- 每次新值到达任意一侧: Flux#combineLatest
- 选择第一个发布者
- 由源序列中的元素触发: switchMap (每个源元素都映射到一个发布者)
- 由发布者序列中的下一个发布者开始触发: switchOnNext
- 按顺序: Flux#concat 或
- 重复一个已经存在的序列
repeat
(Flux|Mono)- …按时间间隔:
Flux.interval(duration).flatMap(tick → myExistingPublisher)
- …按时间间隔:
- 有一个空的序列后
- 有一个序列 但不需要他的值:
ignoreElements
(Flux.ignoreElements()|Mono.ignoreElement())- …完成表示为一个 Mono<Void>:
then
(Flux|Mono) - …在最后等待另一个任务完成:
thenEmpty
(Flux|Mono) - …在最后切换为另一个 Mono : Mono#then(mono)
- …在最后发出一个值: Mono#thenReturn(T)
- …在最后切换为一个Flux:
thenMany
(Flux|Mono)
- …完成表示为一个 Mono<Void>:
- 有一个需要推迟完成的Mono…
- 直到这个值派生的另一个发布者完成: Mono#delayUntil(Function)
- 我想递归地将元素扩展为序列图并发出组合…
窥探序列(Peek)
- 在不改变最终序列的情况下
- 获得通知/执行其他行为(有时称为“副作用”):
- 发布/发射(emissions):
doOnNext
(Flux|Mono) - 完成(completion): Flux#doOnComplete, Mono#doOnSuccess (如果有的话 包括结果)
- 发生错误接受(error termination):
doOnError
(Flux|Mono) - 取消(cancellation):
doOnCancel
(Flux|Mono) - 在序列的开始:
doFirst
(Flux|Mono) - subscription之后(ack之后) :
doOnSubscribe
(Flux|Mono)Subscription
的确认在subscribe
之后- 相当于绑定到Subscriber#onSubscribe(Subscription)
- 被请求(request):
doOnRequest
(Flux|Mono) - 完成(complete)或错误结束(error):
doOnTerminate
(Flux|Mono) - 任何类型的信号 Signal:
doOnEach
(Flux|Mono) - 任何终止条件 (complete, error, cancel):
doFinally
(Flux|Mono)
- 发布/发射(emissions):
- 记录内部发生的事情:
log
(Flux|Mono)
- 获得通知/执行其他行为(有时称为“副作用”):
- 想知道所有事件:
过滤序列(filter)
- 过滤一个序列:
- 基于任意标准:
filter
(Flux|Mono) - 限制发射对象的类型:
ofType
(Flux|Mono) - 通过完全忽略这些值:
ignoreElements
(Flux.ignoreElements()|Mono.ignoreElement()) - 通过忽略重复的值:
- 在整个序列中: Flux#distinct
- 在随后发出的项目之间 (deduplication): Flux#distinctUntilChanged
- 基于任意标准:
- 保留序列的一个子集:
- 通过取n个元素:
- 从序列起始的位置: Flux#take(long, true)
- …向上游无限量请求: Flux#take(long, false)
- …基于持续事件: Flux#take(Duration)
- …仅取第一个元素作为 Mono: Flux#next()
- …使用request(n)而不是取消: Flux#limitRequest(long)
- 在队列的末尾: Flux#takeLast
- 直到满足条件 (包括): Flux#takeUntil (基于断言), Flux#takeUntilOther (基于同伴发布者)
- 满足条件时 (不包括): Flux#takeWhile
- 从序列起始的位置: Flux#take(long, true)
- 最多取一个元素:
- 在特定的位置: Flux#elementAt
- 在结尾: .takeLast(1)
- …如果是空的就发布一个错误信号: Flux#last()
- …如果是空的发布一个默认数据信号: Flux#last(T)
- 通过跳过元素:
- 在序列起始位置: Flux#skip(long)
- …基于一个时间间隔: Flux#skip(Duration)
- 在序列末尾: Flux#skipLast
- 直到满足任意条件 (包括): Flux#skipUntil (predicate-based), Flux#skipUntilOther (companion publisher-based)
- 满足条件时(不包括): Flux#skipWhile
- 在序列起始位置: Flux#skip(long)
- 通过抽样项目:
- 按持续时间: Flux#sample(Duration)
- 但保留采样窗口中的第一个元素而不是最后一个元素: sampleFirst
- 通过一个基于发布者的窗口: Flux#sample(Publisher)
- 基于发布者"超时": Flux#sampleTimeout (每个元素触发一个发布者 如果发布者与下个发布者不重叠 则发出)
- 按持续时间: Flux#sample(Duration)
- 通过取n个元素:
- 期待只有一个元素 (如果超过一个则报错)…
- 同时 如果序列是空的也需要报错: Flux#single()
- 同时 如果序列是空的提供一个默认值: Flux#single(T)
- 同时 也接受空序列: Flux#singleOrEmpty
错误处理
- 创建一个错误序列:
error
(Flux|Mono)… - 需要与try/catch等效的处理:
- 从错误中恢复…
- 通过回退:
- 回退到一个值:
onErrorReturn
(Flux|Mono) - 回退到一个 Publisher 或 Mono, 根据错误可能不同: Flux#onErrorResume 和 Mono#onErrorResume
- 回退到一个值:
- 通过重试…
- 通过回退:
- 处理背压"错误" (从上游请求最大值并在下游没有产生足够请求时使用该策略)
- 通过抛出一个特殊的 IllegalStateException: Flux#onBackpressureError
- 通过删除多余的值s: Flux#onBackpressureDrop
- …除了最后一个: Flux#onBackpressureLatest
- 通过缓冲多余的值 有界或无界的): Flux#onBackpressureBuffer
- …并在游街缓冲区也溢出时应用策略: Flux#onBackpressureBuffer 和 BufferOverflowStrategy
时间相关处理
- 将发布关联到一个可测量的时间…
- …提供可获取的最好的精度和功能性:
timed
(Flux|Mono)- Timed<T>#elapsed() 的 Duration自从最后的
onNext
- Timed<T>#timestamp() 的 Instant epoch 时间戳 表示(毫秒分辨率)
- Timed<T>#elapsedSinceSubcription() 的 Duration 自订阅以来的持续时间 (而不是最后一个onNext)
- 过去的持续时间可以具有纳秒级的时间分辨率Durations
- Timed<T>#elapsed() 的 Duration自从最后的
- …作为一个 (legacy) Tuple2<Long, T>…
- …提供可获取的最好的精度和功能性:
- 如果发布之间有太多延迟 就打断序列:
timeout
(Flux|Mono) - 从时钟获取有规律的定期时间间隔: Flux#interval
- 在初始的延迟后获取数据信号
0
: static Mono.delay. - 引入一个延迟:
- 在每个onNext信号之间: Mono#delayElement, Flux#delayElements
- 在订阅发生之前:
delaySubscription
(Flux|Mono)
分割一个序列
- 通过边界标准将一个 Flux<T> 分割为一个
Flux<Flux<T>>
- 通过尺寸大小: window(int)
- …有丢弃或重叠的窗口: window(int, int)
- 通过时间 window(Duration)
- …有丢弃或重叠的窗口: window(Duration, Duration)
- 通过时间或尺寸(当达到指定数量或指定超时时限时窗口关闭): windowTimeout(int, Duration)
- 基于元素的断言(predicate): windowUntil
- ……在下一个窗口发出触发边界的元素 (
cutBefore
的变体): .windowUntil(predicate, true) - …在元素匹配一个断言时保持打开状态: windowWhile (不匹配的元素不被发布)
- ……在下一个窗口发出触发边界的元素 (
- 由控件 Publisher 中的 onNexts 表示的任意边界驱动: window(Publisher), windowWhen
- 通过尺寸大小: window(int)
- 我想将 Flux<T> 和边界内的缓冲区元素拆分在一起…
- 组成 List:
- 通过大小边界: buffer(int)
- …有重叠或丢弃的缓冲区: buffer(int, int)
- 按持续时间边界: buffer(Duration)
- …有重叠或丢弃的缓冲区: buffer(Duration, Duration)
- 按大小或持续时间边界: bufferTimeout(int, Duration)
- 通过任意标准的边界: bufferUntil(Predicate)
- …将触发边界的元素放入下一个缓冲区: .bufferUntil(predicate, true)
- …在断言匹配时进行缓冲并删除触发边界的元素: bufferWhile(Predicate)
- 由空间publisher中的onNexts表示的任意边界驱动: buffer(Publisher), bufferWhen
- 通过大小边界: buffer(int)
- 组成任意类型的集合
C
: 使用变种的方法 如 buffer(int, Supplier<C>)
- 组成 List:
- 拆分Flux<T> 使共享特征的元素最终位于相同的子通量: groupBy(Function<T,K>) TIP: 注意
Flux<GroupedFlux<K, T>>
,
内部的每一个 GroupedFlux 公用同一个K
key 可以通过key()访问.
同步的操作
Note:
如果从标记为"仅非阻塞"的调度程序中调用(默认为parallel()和single())
除了Mono#toFuture之外的方法都将抛出UnsupportedOperatorException
- 对 Flux<T> 的操作:
- 阻塞直到可以获取第一个元素: Flux#blockFirst
- …带有超时时限的: Flux#blockFirst(Duration)
- 阻塞直到可以获取最后一个元素 (如果是空的序列则为 null): Flux#blockLast
- …带有超时时限的: Flux#blockLast(Duration)
- 同步的切换为一个 Iterable<T>: Flux#toIterable
- 同步的切换为一个Java 8 Stream<T>: Flux#toStream
- 阻塞直到可以获取第一个元素: Flux#blockFirst
- 对 Mono<T> 的操作:
- 阻塞直到可以获取值: Mono#block
- …代超时时限的: Mono#block(Duration)
- 转换为一个 CompletableFuture<T>: Mono#toFuture
- 阻塞直到可以获取值: Mono#block
Flux广播给多个订阅者
- 将多个订阅者(Subscriber)连接到一个Flux
- 并决定何时触发源 connect(): publish() (返回一个 ConnectableFlux)
- 并立即触发源 (后来的订阅者只能获取后面的数据:
share()
(Flux|Mono)- 当足够的注册者注册时永久连接到源: .publish().autoConnect(n)
- 当订阅者数量高于/低于阈值时自动连接或取消源: .publish().refCount(n)
- …但在取消前让新订阅者有机会进入: .publish().refCount(n, Duration)
- 缓存来自发布者(Publisher)的数据并将其重播给以后的订阅者:
- 最多
n
个元素: cache(int) - 缓存在持续时间内的最新元素 Duration (生存时间):
cache(Duration)
(Flux|Mono)- …但保留最多
n
个元素: cache(int, Duration)
- …但保留最多
- 但不立即触发源: Flux#replay (返回一个 ConnectableFlux)
- 最多