描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787121364174丛书名: Java编程方法论系列丛书
2. 知秋是国内为数不多的响应式和NIO方向的专家,本书是讲解响应式技术的书籍,在进行源码导读的同时,也引导读者对代码设计进行思考。
3. 响应式是未来的编程趋势,本书深入解读响应式RxJava 2的源码,从设计到实现细节,帮助读者达到RxJava 2源码库组件级别的拓展。
4. 本书包含大量案例,案例按照功能迭代的方式进行讲解,另外作者还录制了相关视频,可以配合学习。
1.1 异步编程模式 1
1.1.1 并发 2
1.1.2 并行开发初探 3
1.2 流(Stream) 3
1.3 响应式流(Reactive Stream) 4
1.3.1 响应式流的特性 4
1.3.2 响应式开发的设计原则 5
1.3.3 响应式开发的好处 6
1.4 响应式开发工具库 6
1.4.1 RxJava简介 6
1.4.2 Reactor简介 7
1.4.3 MongoDB简介 8
1.4.4 响应式项目用例 8
1.5 Java 9中的响应式编程 10
1.5.1 响应式编程接口 10
1.5.2 Java 9响应式编程入门Demo 12
1.5.3 SubmissionPublisher类的源码解读 18
1.5.4 响应式编程整合Spring实战案例 23
1.6 小结 29
第2章 在RxJava中创建Observable 30
2.1 响应式编程所涉及的设计模式 30
2.1.1 观察者模式 30
2.1.2 迭代器模式 30
2.2 解读reactivex.Observable 31
2.2.1 从Flow.Publisher到Observable 33
2.2.2 subscribe的二三事 33
2.2.3 create方法的设计思想 36
2.2.4 各式各样的Observable 40
2.2.5 Observable.cache 43
2.2.6 无限流 49
2.2.7 在Observable内处理错误 54
2.2.8 定时控制Observable发送数据 56
2.2.9 Disposable延伸 59
2.2.10 ConnectableObservable解读 67
2.2.11 Observable中的publish.refCount解读 76
2.2.12 RxJava中的Subject解读 79
2.3 小结 89
第3章 RxJava 2中的操作 90
3.1 核心操作 90
3.1.1 使用filter进行条件过滤 90
3.1.2 使用map进行元素转换 96
3.1.3 使用flatMap进行扁平化转换 98
3.1.4 使用scan累加器 112
3.1.5 使用groupBy进行分组 114
3.2 多个Observable的合并操作 122
3.2.1 使用merge对Observable进行合并 122
3.2.2 使用zip方法进行合并 124
3.2.3 combineLatest操作 135
3.2.4 withLatestFrom操作 141
3.2.5 amb操作 142
3.3 高级操作 143
3.3.1 再谈累加器scan 143
3.3.2 聚合操作reduce 144
3.3.3 收集操作collect 146
3.3.4 使用distinct去重 148
3.3.5 使用distinctUntilChanged过滤重复数据 152
3.3.6 其他操作 152
3.3.7 自定义操作 153
3.4 小结 159
第4章 对RxJava 2的设计探索 160
4.1 源的创建设计思路 160
4.2 中间操作的转承 162
4.3 小结 166
第5章 Observable实战 167
5.1 初版架子实现 167
5.1.1 DAO层面的处理工作 167
5.1.2 控制层的响应式实现 172
5.2 基于架子实现一个汇率查询的服务 175
5.3 rxjava-web-spring-boot-starter的抽取设计 179
5.4 ObservableSseEmitter的设计实现 188
5.5 小结 196
第6章 RxJava 2中的多线程操作 197
6.1 初探RxJava并发编程 197
6.2 subscribeOn操作 211
6.3 observeOn操作 216
6.4 unsubscribeOn操作 220
6.5 调度器Scheduler 226
6.5.1 Schedulers.newThread方式 227
6.5.2 Schedulers.io方式 227
6.5.3 Schedulers.computation方式 228
6.5.4 Schedulers.from(Executor executor)自定义方式 228
6.6 小结 230
第7章 Flowable与背压 231
7.1 回顾背压 231
7.2 引入Flowable 233
7.3 探索Flowable.create 234
7.3.1 BackpressureStrategy.BUFFER策略 239
7.3.2 BackpressureStrategy.LATEST策略 246
7.3.3 BackpressureStrategy.DROP策略 249
7.4 将一个Observable转化为一个Flowable 251
7.5 通过onBackpressureXXX操作来实现背压策略 252
7.5.1 onBackPressureBuffer操作 255
7.5.2 onBackpressureLatest与onBackpressureDrop操作 256
7.6 Flowable.generate操作 257
7.7 小结 262
第8章 Flowable实战 263
8.1 使用Flowable封装JDBC 263
8.1.1 封装部分查询逻辑 263
8.1.2 封装update逻辑 265
8.2 结合Spring Web应用使用Flowable 268
8.2.1 接口数据的获取 269
8.2.2 响应式服务的源设计 271
8.3 单元测试 274
8.3.1 使用Mock Service Server进行测试 274
8.3.2 使用@Mock来进行一些服务测试 277
8.4 controller层的实现逻辑改造 279
8.5 小结 282
本书是“Java编程方法论系列丛书”的第一本书,“Java编程方法论系列丛书”将我多年的代码经验通过讲述优秀的RxJava 2、Reactor 3、Reactor-Netty与Spring WebFlux等框架库的源码细节展现出来,目的是让大家可以学习一种读源码的方式。也就是说,看源码不仅要看懂它干了什么,而且更应该看相关源码的设计思路以及技巧。这就好比研读一篇好文章一样,要揣摩作者的行文方式。
与理解代码相比,我更愿意带给大家的是一种生活态度。Java的第一个身份是语言,语言是用于描述我们的思想和生活的,所以带着生活中的理念来读源码,你就会发现情况大为不同:各种编程技巧和实现思路通通摆在了你的眼前。本系列丛书就是从这个角度出发的,所以针对的读者是那些想要提高自己对于基础代码掌控能力的中高级程序员。
下面具体介绍一下本书内容。本书主要讲解了到底什么是响应式,从代码设计层面将JDK 9 中的Flow API、RxJava 2中关于源的创建,以及调度与背压等相关核心操作娓娓道来,并通过实战案例帮助大家更好地理解和使用相关的API。本书涉及了大量并发编程方面的技巧,以及从基础代码角度介绍了各种接口、设计模式和与之相关的基础知识点,并将它们融会贯通。这就好比我们上学的时候,老师向我们传授基础知识,然后通过习题让我们掌握这些基础知识的运用技巧。本书也遵循了这个思路,同时这也符合我写书的初衷。
限于篇幅,有些内容没能完全在书中呈现,为了降低图书的阅读理解难度,我专门录制了相关的分享视频,可以更直观地带领大家走进源码世界。视频可以说是图书的有益补充,欢迎大家观看、学习。另外,希望读者通过学习本书了解响应式编程如何带来程序性能的提升以及其正确的使用方式。在录制本系列丛书的另一本书《Java编程方法论:响应式Reactor 3、Reactor-Netty和Spring WebFlux》(后续出版)的相关视频时,使我感到很荣幸的是,视频得到了Spring官方的肯定,并在Spring官方推特和博客上进行了宣传、推广,这增加了我对本系列丛书的信心。
最后,感谢尹相宇同学,没有你听我啰啰唆唆地讲代码,我估计自己的这份激情难以维持,当然,这本书的顺利出版也离不开你的审阅。另外,需要感谢的还有付睿编辑,她帮助我修正了很多表达细节上的错误。最后,感谢我的家人对我的理解和默默付出。
知秋(李飞)
2019年2月15日
推荐序一
在Architecture and Design InfoQ Trends Report – January 2019 (2019年1月的InfoQ架构和设计趋势报告)中,响应式编程(Reactive Programming)和函数式编程(Functional Programming)编列在第一季度(Q1)的Early Adopter(早期采纳者)中。尽管这仅是一家之言,但是不少开发人员逐渐意识到响应式之风已然吹起。也许你的生产系统尚未出现响应式的身影,不过你可能听说过Spring WebFlux或Netflix Hystrix等开源框架。笔者曾请教过Pivotal(Spring母公司)的布道师Josh Long :“Spring技术栈未来的重心是否要布局在响应式上?”对方的答复是:“没错,响应式是未来的趋势。”同时,越来越多的开源项目开始签署响应式宣言(The Reactive Manifesto) 并喊出了“Web Are Reactive”的口号。
或许开源界的种种举动无法说服你向响应式的“港湾”中停靠,不过Java 9中Flow API 的引入,又给业界注入了一剂“强心针”。不难看出,无论是Java API,还是Java框架,均走向了响应式编程模型的道路,这并非一种巧合。
通常,人们谈到的响应式可与响应式编程画等号,以“非阻塞(Non-Blocking)”和“异步(Asynchronous)”的特性并述,以数据结构与操作相辅相成。响应式编程涉及函数式和并发两种编程模型,前者关注语法特性,后者强调执行效率。简言之,响应式编程的意图在于“Less Code,More Efficient”。除此之外,笔者认为响应式更大的价值在于统一Java并发编程模型,使得同步和异步的实现代码无异,同时做到Java编程风格与其他编程语言更好地融合,或许你已经发现Java与JavaScript在响应式方面并不存在本质区别。纵观Java在响应式编程上的发展,其特性更新真可谓步步为营、如履薄冰。尽管Java线程API Thread与Runnable已具备异步以及非阻塞的能力,然而其同步和异步编程的模式并不统一,并且理解Thread API的细节和管理线程生命周期的成本均由开发人员承受。虽然在Java 5引入J.U.C框架(Java并发框架)之后,ExecutorService的实现减轻了以上负担,但是开发人员仍须关注ExecutorService的实现细节。比如,怎样合理地设置线程池空间及阻塞队列又成为新挑战。为此,Java 7引入了ForkJoinPool API,不过此时的J.U.C框架与响应式理念仍存在距离,即使是线程安全的数据结构也并不具备并行计算的能力(如集合并行排序),同时操作集合的手段也相当贫乏,缺少类似Map/Reduce等的操作。不过这些困难只是暂时的,终究会被Java 8“救赎”。Stream API的出现不仅具备数据操作在串行和并行间自由切换的能力(如sequential()及parallel()方法),而且淡化了并发的特性(如sorted()方法既可以进行传统排序,也可以进行并行排序)。相同的设计哲学也体现在Java响应式实现框架中,如本书中提及的RxJava API io.reactivex.Observable。统一编程模型只是流的设计目标之一,它结合Lambda语法特性,虽然提供了数量可观的操作方法,如flatMap()方法等,但是无论对比RxJava,还是Reactor ,流操作方法却又相形见绌。值得一提的是,这些操作方法在响应式的术语中被称为操作符(Operator)。当然框架内建操作符的多与少,并非判断其是否为响应式实现的依据。其中的决定性因素在于数据必须来自发布端(生产者)的“推送(Push)”,而非消费端的“拉取(Pull)”。显然,流属于消费端已就绪(Ready)的数据集合,并不存在其他数据推送源。不过JVM语言早期的响应式定义处于模糊地带,如RxJava API属于观察者模式(Observer Pattern) 的扩展,而非迭代器模式(Iterator Pattern) 的实现。而Reactor的实现则拥抱响应式流规范 ,该规范中消费端对于数据的操作是被动地处理,而非主动地索取。换言之,数据的到达存在着不确定性 。当推送的数据无法得到消费端的及时响应时,响应式框架必须提供背压(Back Pressure) 实现,确保消费端拥有“拒绝的权力(cancel)”。在此理论基础上,响应式流规范定义了一套抽象的API,作为Java 9中java.util.concurrent.Flow API的顶层设计。不过关于操作符的部分,该规范似乎不太关心,这也是RxJava和Reactor均称自身为响应式扩展框架的原因,同时两者在API级别提供了多种调度器(Scheduler) 实现,可适配不同并发场景。尽管响应式定义在不同的阵营之间存在差异,但援引本人在《Reactive Programming:一种技术,各自表述》 一文中的总结:
Reactive Programming作为观察者(Observer)模式的延伸,不同于传统的命令编程(Imperative Programming)同步拉取数据的方式,如迭代器模式(Iterator),而是采用数据发布者同步或异步地推送到数据流(Data Stream)的方案。当该数据流(Data Stream)的订阅者监听到变化传播时,立即做出响应动作。在实现层面上,响应式编程可结合函数式编程简化面向对象语言语法的臃肿性,屏蔽并发实现的复杂细节,提供数据流的有序操作,从而达到提升代码的可读性以及减少Bug出现的目的。同时,响应式编程结合背压(Back Pressure)的技术解决了发布端生成数据的速度高于订阅端消费数据的速度的问题。
不难看出,响应式是一门综合的编程艺术,在实现框架的“加持”下,相同的代码逻辑可实现同步与异步非阻塞功能,从而达到提升应用整体性能的目的。不过现实的情况或许没有那么理想,Spring官方文档在“Web on Reactive Stack”章节中提到,“响应式和非阻塞通常并不会让应用运行得更快” :
Reactive and non-blocking generally do not make applications run faster.
为此,JHipster 给出了一份Spring 5 WebFlux性能测试报告 ,其中一条结论是“响应式应用并没有表现出速度的提升(甚至其速度变得更慢)”:
No improvement in speed was observed with our reactive apps (the Gatling results are even slightly worse).
数月后,看似相反的结论却在DZone 的一篇名为Raw Performance Numbers – Spring Boot 2 Webflux vs. Spring Boot 1 的文章中出现,测试结果是Spring Boot 2 WebFlux在高并发下的响应时间更平稳。实际上,这个测试结果有些“关公战秦琼”的味道,毕竟Spring Boot 2下的WebFlux和Spring Boot 1下的Servlet容器所使用的线程模型是不同的,并且Serv
朱勇铭 携程框架架构部 Java高级工程师
Spring 5发布之后,它带来了响应式Web开发框架WebFlux 。此时,响应式编程真正开始进入大多数Java后端开发工程师的视野。然而,国内在响应式编程的资料方面,绝大多数停留在入门使用层面。而本书,从入门到实战,继而到原理、源码,都进行了很好的覆盖。并且,本书的作者在两年前已经开始落地实践响应式编程了,相信本书可以为我们提供很好的学习体验和实战经验。
芋艿 “芋道源码”博主
本书解密了响应式编程之美,深入浅出地介绍了响应式模式及源码。读完本书,可以掌握规范、合理的响应式设计,以及高质量的响应式代码实践。在大多数场景下,提高资源利用率很重要,尤其对于微服务下I/O密集型等场景来说尤其如此。
泥瓦匠BYSocket 博主
评论
还没有评论。