1、SpringBoot 使用
1.1、Spring Core 中的响应式
Spring 生态系统的核心模块是Spring Core 模块。Spring 5.x 引入对响应式流和响应式库的原生支持,其中,响应式库包含RxJava 1/2 和Project Reactor 3。
1.1.1、响应式类型转换支持
为了支持响应式流规范所进行的最全面的改进之一是引入了 ReactiveAdapter 和 ReactiveAdapterRegistry 。ReactiveAdapter 类为响应式类型转换提供了两种基本方法,用于将任何类型转换为 Publisher<T> 并将其转换回 Object 。如以下源码所示:
org.springframework.core.ReactiveAdapter#toPublisher
org.springframework.core.ReactiveAdapter#fromPublisher
如,为了提供对RxJava 2 中的Maybe 响应式类型的转换,我们可以通过以下方式创建自己的 ReactiveAdapter:
/**
* 适配器的构造器,包含了异步类型或响应式类型与Reactive Streams Publisher之间的相互转换。
*
* @param descriptor 响应式类型描述符
* @param toPublisherFunction 转换到Publisher的适配器
* @param fromPublisherFunction 从Publisher转换的适配器
*/
public MayBeReactiveAdapter(
ReactiveTypeDescriptor descriptor,
Function<Object, Publisher<?>>
toPublisherFunction,
Function<Publisher<?>, Object>
fromPublisherFunction) {
super(descriptor, toPublisherFunction, fromPublisherFunction);
}
public MayBeReactiveAdapter() {
super(
ReactiveTypeDescriptor.singleOptionalValue(Maybe.class,Maybe::empty),
rawMaybe -> ((Maybe<?>) rawMaybe).toFlowable(),
publisher -> Flowable.fromPublisher(publisher).singleElement()
);
}
上面实例中,扩展了默认的 ReactiveAdapter 并提供了一个自定义实现。父构造函数的第一个参数是 ReactiveTypeDescriptor 实例的定义。ReactiveTypeDescriptor 提供了有关 ReactiveAdapter 中使用的响应式类型的信息。父构造函数需要定义转换函数,而该函数将原始对象( Maybe )转换为 Publisher 并将任何 Publisher 转换回 Maybe 。
为简化交互, ReactiveAdapterRegistry 使我们能将 ReactiveAdapter 的实例保存在一个位置并提供对它们的通用访问。如以下代码所示:
ReactiveAdapterRegistry.getSharedInstance().registerReactiveType(
ReactiveTypeDescriptor.singleOptionalValue(Maybe.class,Maybe::empty),
rawMaybe -> ((Maybe < ? > ) rawMaybe).toFlowable(),
publisher -> Flowable.fromPublisher(publisher).singleElement()
);
// 后续使用的时候直接通过共享实例访问
ReactiveAdapter maybeAdapter = ReactiveAdapterRegistry.getSharedInstance()
.getAdapter(Maybe.class);
如代码所示,ReactiveAdapterRegistry 表示针对不同响应式类型的ReactiveAdapter实例的公共池。同时,ReactiveAdapterRegistry 提供了一个单例实例,该实例既可以在框架内的许多地方使用,也可以在开发的应用程序中使用。
1.1.2、响应式IO
Spring Core 模块在 byte 缓冲区实例上引入了一个称为 DataBuffer 的抽象。之所以避免使用 java.nio.ByteBuffer ,主要是为了提供一个既可以支持不同字节缓冲区,又不需要在它们之间进行任何额外的转换的抽象。
例如,为了将 io.netty.buffer.ByteBuf 转换为 ByteBuffer ,必须访问所存储的字节,而这些字节可能需要从堆外空间被拉入到堆中。这可能破坏Netty 提供的高效内存使用和缓冲区回收(重用相同的字节缓冲区)。
Spring DataBuffer 提供特定实现的抽象,能以通用方式使用底层实现。DataBuffer 的 PooledDataBuffer 子接口,还启用了引用计数功能,并支持开箱即用的高效内存管理。
此外,Spring Core 的第五版引入了 DataBufferUtils 类,能以响应式流的形式与I/O 进行交互(与网络、资源、文件等交互)。例如,可以基于背压支持并通过以下响应式的方式读取文件内容:
Flux<DataBuffer> reactiveHamlet = DataBufferUtils.read(
new DefaultResourceLoader().getResource("Java入门到回家.txt"),
new DefaultDataBufferFactory(),
1024
);
DataBufferUtils.read 返回一个 DataBuffer 实例的 Flux 。因此,可以使用 Reactor 的所有功能读取文件内容。最后,与Spring Core 中响应式相关的最后一个意义重大且不可或缺的特性是响应式编解码器(reactive codecs)。响应式编解码器提供了一种将 DataBuffer 实例流 和