Reactor实例解析

\

要点

\\
  • Reactor是一个运行在Java8之上的响应式流框架,它提供了一组响应式风格的API\\t
  • 除了个别API上的区别,它的原理跟RxJava很相似\\t
  • 它是第四代响应式框架,支持操作融合,类似RxJava 2\\t
  • Spring 5的响应式编程模型主要依赖Reactor\
\\

RxJava回顾

\\

Reactor是第四代响应式框架,跟RxJava 2有些相似。Reactor项目由Pivotal启动,以响应式流规范、Java8和ReactiveX术语表为基础。它的设计是Reactor 2(上一个主要版本)和RxJava核心贡献者共同努力的结果。

\\

在之前的同系列文章“RxJava实例解析”和“测试RxJava”里,我们已经了解了响应式编程的基础:数据流的概念、Observable类和它的各种操作以及通过工厂方法创建静态和动态的Observable对象。

\\

Observable是事件的源头,Observer提供了一组简单的接口,并通过订阅事件源来消费Observable的事件。Observable通过onNext向Observer通知事件的到达,后面可能会跟上onError或onComplete来表示事件的结束。

\\

RxJava提供了TestSubscriber来测试Observable,TestSubscriber是一个特别的Observer,可以用它断言流事件。

\\

在这篇文章里,我们将会对Reactor和RxJava进行比较,包括它们的相同点和不同点。

\\

Reactor的类型

\\

Reactor有两种类型,Flux\u0026lt;T\u0026gt;Mono\u0026lt;T\u0026gt;。Flux类似RaxJava的Observable,它可以触发零到多个事件,并根据实际情况结束处理或触发错误。

\\

Mono最多只触发一个事件,它跟RxJava的SingleMaybe类似,所以可以把Mono\u0026lt;Void\u0026gt;用于在异步任务完成时发出通知。

\\

因为这两种类型之间的简单区别,我们可以很容易地区分响应式API的类型:从返回的类型我们就可以知道一个方法会“发射并忘记”或“请求并等待”(Mono),还是在处理一个包含多个数据项的流(Flux)。

\\

Flux和Mono的一些操作利用了这个特点在这两种类型间互相转换。例如,调用Flux\u0026lt;T\u0026gt;的single()方法将返回一个Mono\u0026lt;T\u0026gt;,而使用concatWith()方法把两个Mono串在一起就可以得到一个Flux。类似地,有些操作对Mono来说毫无意义(例如take(n)会得到n\u0026gt;1的结果),而有些操作只有作用在Mono上才有意义(例如or(otherMono))。

\\

Reactor设计的原则之一是要保持API的精简,而对这两种响应式类型的分离,是表现力与API易用性之间的折中。

\\

“使用响应式流,基于Rx构建”

\\

正如“RxJava实例解析”里所说的,从设计概念方面来看,RxJava有点类似Java 8 Steams API。而Reactor看起来有点像RxJava,不过这决不只是个巧合。这样的设计是为了能够给复杂的异步逻辑提供一套原生的具有Rx操作风格的响应式流API。所以说Reactor扎根于响应式流,同时在API方面尽可能地与RxJava靠拢。

\\

响应式类库和响应式流的使用

\\

Reactive Streams(以下简称为RS)是“一种规范,它为基于非阻塞回压的异步流处理提供了标准”。它是一组包含了TCK工具套件和四个简单接口(Publisher、Subscriber、Subscription和Processor)的规范,这些接口将被集成到Java 9.

\\

RS主要跟响应式回压(稍后会详细介绍)以及多个响应式事件源之间的交互操作有关。它并不提供任何操作方法,它只关注流的生命周期。

\\

Reactor不同于其它框架的最关键一点就是RS。Flux和Mono这两者都是RS的Publisher实现,它们都具备了响应式回压的特点。

\\

在RxJava 1里,只有少部分操作支持回压,RxJava 1的Observable并没有实现RS里的任何类型,不过它有一些RS类型的适配器。可以说,RxJava 1实际上比RS规范出现得更早,而且在RS规范设计期间,RxJava 1充当了函数式工作者的角色。

\\

所以,你在使用那些Publisher适配器时,它们并不会为你提供任何操作。为了能做一些有用的操作,你可能需要用回Observable,而这个时候你需要另一个适配器。这种视觉上的混乱会破坏代码的可读性,特别是像Spring 5这样的框架,如果整个框架建立在这样的Publisher之上,那么就更是杂乱不堪。

\\

RS规范不支持null值,所以在从RxJava 1迁移到Reactor或RxJava 2时要注意这点。如果你在代码里把null用作特殊用途,那么就更是要注意了。

\\

RxJava 2是在RS规范之后出现的,所以它直接在Flowable类型里实现了Publisher。不过除了RS类型,RxJava 2还保留了RxJava 1的“遗留”类型(Observable、Completable和Single)并且引入了其它一些可选类型——Maybe。这些类型提供了不同的语义,不过它们并没有实现RS接口,这是它们的不足之处。跟RxJava 1不一样,RxJava 2的Observable不支持RxJava 2的回压协议(只有Flowable具备这个特性)。之所以这样设计是为了能够为一些场景提供一组丰富且流畅的API,比如用户界面发出的事件,在这样的场景里是不需要用到回压的,而且也不可能用到。Completable、Single和Maybe不需要支持回压,不过它们也提供了一组丰富的API,而且在被订阅之前不会做任何事情。

\\

在响应式领域,Reactor变得愈加精益,它的Mono和Flux两种类型都实现了Publisher,并且都支持回压。虽然把Mono作为一个Publisher需要付出一些额外的开销,不过Mono在其它方面的优势弥补了它的缺点。在后续部分我们将看到对Mono来说回压意味着什么。

\\

相比RxJava,API相似但不相同

\\

ReactiveX和RxJava的操作术语表有时候真的难以掌握,因为历史原因,有些操作的名字让人感到困惑。Reactor尽量把API设计得紧凑,在给API取名时尽量选择好一点的名字,不过总的来说,这两套API看起来还是很相像。在最新的RxJava 2迭代版本中,RxJava 2借鉴了Reactor的一些术语,这预示着这两个项目之间可能会有越来越紧密的合作。一些操作和概念总是先出现在其中的一个项目里,然后互相借鉴,最后会同时渗透到两个项目里。

\\

例如,Flux也有常见的just工厂方法(虽然只有两种变形:接受一个参数或变长参数)。不过from方法有很多个变种,最值得一提的是fromIterable。当然,Flux也包含了那些常规的操作:map、merge、concat、flatMap、take,等等。

\\

Reactor把RxJava里令人困惑的amb操作改成了看起来更加中肯的firstEmitting。另外,为了保持API的一致,toList被重新命名为collectList。实际上,所有以collect开头的操作都会把值聚合到一个特定类型的集合里,不过只会为每个集合生成一个Mono。而所有以to开头的操作被保留用于类型转换,转换之后的类型可以用于非响应式编程,例如toFuture()。

\\

在类初始化和资源使用方面,Reactor之所以也能表现得如此精益,要得益于它的融合特性:Reactor可以把多个串行的操作(例如调用concatWith两次)合并成单个操作,这样就可以只对这个操作的内部类做一次初始化(也就是macro-fusion)。这个特性包含了基于数据源的优化,抵消了Mono在实现Publisher时的一些额外开销。它还能在多个相关的操作之间共享资源(也就是micro-fusion),比如内部队列。这些特性让Reactor成为不折不扣的的第四代响应式框架,不过这个超出了这篇文章的讨论范围。

\\

下面让我们来看看几个Reactor的操作。

\\

一些操作示例

\\

(这一小节包含了一些代码片段,我们建议你动手去运行它们,深入体验一下Reactor。所以你需要打开IDE,并创建一个测试项目,把Reactor加入到依赖项里。)

\\

对于Maven,可以把下面的依赖加到pom.xml里:

\\
\\u0026lt;dependency\u0026gt;\    \u0026lt;groupId\u0026gt;io.projectreactor\u0026lt;/groupId\u0026gt;    \    \u0026lt;artifactId\u0026gt;reactor-core\u0026lt;/artifactId\u0026gt;\    \u0026lt;version\u0026gt;3.0.3.RELEASE\u0026lt;/version\u0026gt;\\u0026lt;/dependency\u0026gt;
\\

对于Gradle,要把Reactor作为依赖项,类似这样:

\\
\dependencies {\    compile \"io.projectreactor:reactor-core:3.0.3.RELEASE\"\}
\\

我们来重写前面几篇同系列文章里的例子!

\\

Observable的创建跟在RxJava里有点类似,在Reactor里可以使用just(T...)和fromIterator(Iterable\u0026lt;T\u0026gt;)工厂方法来创建。just方法会把List作为一个整体触发,而fromIterable会逐个触发List里的每个元素:

\\
\public class ReactorSnippets {\  private static List\u0026lt;String\u0026gt; words = Arrays.asList(\        \"the\
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值