如何创建反应式“中级订户”?如何将所有Flux <t>零件组合在一起并进一步处理它们的结果链(转换为Mono <r>)?

时间:2018-09-17 12:21:34

标签: java spring-webflux project-reactor reactor

我正在使用spring webflux + mongodb-active将二进制文件(图像)保存到Mongo DB。不幸的是spring-boot-starter-data-mongodb-reactive:2.0.5.RELEASE不支持GridFsTemplate功能的反应式编程。因此,我决定创建一个将包含所有DataBuffer部分,将它们组合并转换为InputStream的Subscriber,这样GridFsTemplate::store将是可能的:

public class GridFsTemplateSubscriber extends BaseSubscriber<DataBuffer> {
private GridFsTemplate gridFsTemplate;
private List<DataBuffer> dataBuffers;
private String fileName;

public GridFsTemplateSubscriber(GridFsTemplate gridFsTemplate, String fileName) {
    this.gridFsTemplate = gridFsTemplate;
    this.fileName = fileName;
    dataBuffers = new ArrayList<>();
}

public void hookOnNext(DataBuffer dataBuffer) {
    dataBuffers.add(dataBuffer);
    request(1);
}

public void hookOnComplete() {
    DefaultDataBufferFactory defaultDataBufferFactory = new DefaultDataBufferFactory();
    InputStream inputStream = defaultDataBufferFactory.join(dataBuffers).asInputStream();
    ObjectId objectId = gridFsTemplate.store(inputStream, fileName);
}
}

问题是我想返回objectId进行进一步处理,但是hookOnComplete是无效类型。甚至更多..我想从这里获取ObjectId的Mono,因此我可以以反应方式进一步处理它。在这种情况下,据我所了解的反应原理,我不应该使用“真实”订户,而是将Flux<T>的结果组合在一起的东西,并且在onComplete时返回Mono<R>。项目反应堆是否具有这种能力?我是反应式编程的新手,所以我可能会错过整个想法,所以请指导我如何实现。

在之前的解决方案中,我使用block()结束了反应式链,所以我得到了ObjectId,接下来我用新链发射了对象ID。但这肯定不是一个好的解决方案。

1 个答案:

答案 0 :(得分:1)

不幸的是,整个方法都在自找麻烦,不建议这样做。

实施Subscriber(即使使用BaseSubscriber)几乎绝不是解决方案。如果您使用的驱动程序库不支持响应流,那么您should probably wrap it as blocking code

这样做会丢失很多功能(运行时行为,背压等),但是如果您的订户实现不完美,至少您不会冒整个应用程序崩溃的风险。

在核心库/驱动程序支持响应流之前,您可能应该坚持使用Spring MVC,该MVC支持异步概念,并且在某些情况下支持Flux Mono返回类型。