写作时间:2019-11-29
Spring Boot: 2.2.1 ,JDK: 1.8, IDE: IntelliJ IDEA
说明
在计算机中,响应式编程或反应式编程(Reactive Programming)是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流,而相关的计算机模型会自动将变化的值通过数据流进行传播。
例如,在命令式编程环境中, a:=b+c
表示将表达式的结果赋给a
,而之后改变b
或c
的值不会影响a
。但在响应式编程中,a
的值会随着b
或c
的更新而更新。
电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"
的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化 。
– 来自:维基百科 - 响应式编程
官方内容
- 响应式编程核心Reactive Core
Reactor是一个没有任何阻塞的平台,并提供高效的管理工具. Reactor直接与Java 功能性 API, 与任何过程状态直接交互。包括:完成状态Completable Future, 数据流Stream 和 过程Duration. - 可扩展接口Typed [0|1|N] Sequences
Reactor 提供了2个响应式API构成(增强了扩展性):
- Flux [N] : 表示可以有多个请求(比如:
request(1).request(2)...
) - Mono [0|1] :表示返回结果可以没有,或者有一个
- 非阻塞Non Blocking IO
兼容微服务架构Microservices Architecture, Reactor 提供了 反压式网络引擎(backpressure-ready network engines), 支持请求协议 HTTP (包括 Websockets), TCP 和 UDP.
在响应式编程的顺序流中,Publisher
生产数据. 默认情况下,Publisher
什么事情都不会发生,知道Subscriber
已经注册到Publisher
, 这表明数据会推送给Subscriber
.
代理回调跟响应式编程对比
传统方式的回调黑洞 例子
userService.getFavorites(userId, new Callback<List<String>>() { // 1
public void onSuccess(List<String> list) { // 2
if (list.isEmpty()) { // 3
suggestionService.getSuggestions(new Callback<List<Favorite>>() {
public void onSuccess(List<Favorite> list) { // 4
UiUtils.submitOnUiThread(() -> { // 5
list.stream()
.limit(5)
.forEach(uiList::show); // 6
});
}
public void onError(Throwable error) { // 7
UiUtils.errorPopup(error);
}
});
} else {
list.stream() // 8
.limit(5)
.forEach(favId -> favoriteService.getDetails(favId, // 9
new Callback<Favorite>() {
public void onSuccess(Favorite details) {
UiUtils.submitOnUiThread(() -> uiList.show(details));
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
}
));
}
}
public void onError(Throwable error) {
UiUtils.errorPopup(error);
}
});
解析:
- 这里有两个回调服务Callback , 一个是处理成功,一个处理错误.
- 第一个服务处理favorite IDs列表.
- 如果列表为空, 会跳转到
suggestionService
. suggestionService
提供列表List<Favorite>
给第二个回调.- 因为要处理UI, 需要确保处理逻辑在UI 线程中处理.
- Java 8 数据流限制了列表容量,这里suggestions只处理了5条 , 并显示在UI.
- 在每个阶段, 处理异常情况.
Back to the favorite ID level. If the service returned a full list, we need to go to the - 如果
favorite IDs
列表不为空,favoriteService
将获得数据,并限制数量一样为5个. - 跟推荐回调一样,在UI线程处理UI内容.
响应式编程的例子
userService.getFavorites(userId) // 1
.flatMap(favoriteService::getDetails) // 2
.switchIfEmpty(suggestionService.getSuggestions()) // 3
.take(5) // 4
.publishOn(UiUtils.uiThreadScheduler()) // 5
.subscribe(uiList::show, UiUtils::errorPopup); // 6
解析:
- 首先,开始于获取用户收藏,是一个数据流Flow.
- 异步处理,获取并组装用户收藏数据,也是一个数据流.
- 如果用户收藏数据流为空,则调用
suggestionService
. - 只需要结果的前5条数据.
- 最后,在UI 线程显示结果数据.
- 响应订阅数据流,如果有数据再UI线程显示,如果有错误弹窗显示错误信息.
上面例子来自 3.2. Asynchronicity to the Rescue?
参考
https://projectreactor.io/
https://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B
http://wiki.jikexueyuan.com/project/android-weekly/issue-145/introduction-to-RP.html
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
https://github.com/reactor/reactor-core
https://projectreactor.io/docs/core/release/reference/index.html
https://github.com/reactor/reactor-core/blob/master/docs/asciidoc/reactiveProgramming.adoc
https://blog.51cto.com/liukang/2090170
https://blog.51cto.com/liukang/2090183
http://springcloud.cn/view/366