Java 反应式存储库
我尝试创建一些基于反应堆栈(Reactor+WebFlux)的基本Spring5应用程序 我的下一个目标是实现能够:Java 反应式存储库,java,spring,project-reactor,Java,Spring,Project Reactor,我尝试创建一些基于反应堆栈(Reactor+WebFlux)的基本Spring5应用程序 我的下一个目标是实现能够: 存书 找到所有的书 我的存储库需要涵盖以下场景: 情景A: 没有人订阅FindAll 某人保存了一本书(id=1) 客户1订阅FindAll Book(id=1)被推送到Client1(Client1保持订阅状态,流未完成!) 某人保存了一本书(id=2) Book(id=2)被推送到Client1(Client1保持订阅状态,流未完成!) 因此,在我看来,这个场景是冷源和热源概
public class InMemoryBookRepository {
private final Map<String, Book> bookMap = new ConcurrentHashMap<>();
private final UnicastProcessor<Book> processor = UnicastProcessor.create();
private final FluxSink<Book> fluxSink = processor.sink(FluxSink.OverflowStrategy.LATEST);
private final Flux<Book> hotFlux = processor.publish().autoConnect();
@Override
public void save(Book book) {
bookMap.put(book.getId(), book);
fluxSink.next(book);
}
@Override
public Flux<Book> findAll() {
//without fromIterable I cannot push books that where saved before someone subscribed
return Flux.fromIterable(bookMap.values())
.concatWith(hotFlux)
//Unfortunately this solution produces duplicates so we need to filter them
.distinct();
}
}
MemoryBookRepository中的公共类{
private final Map bookMap=新ConcurrentHashMap();
专用最终UnicastProcessor=UnicastProcessor.create();
private final FluxSink FluxSink=processor.sink(FluxSink.OverflowStrategy.LATEST);
私有最终流量hotFlux=processor.publish().autoConnect();
@凌驾
公共作废保存(书籍){
bookMap.put(book.getId(),book);
fluxSink.next(book);
}
@凌驾
公共流量findAll(){
//如果没有fromIterable,我就不能在别人订阅之前把保存的书推到哪里
返回Flux.fromIterable(bookMap.values())
.concatWith(热通量)
//不幸的是,此解决方案会产生重复项,因此我们需要对其进行筛选
.distinct();
}
}
Ofc,我不能只使用Cold publisher,因为流将在出版藏书后完成。出于同样的原因,我不能使用Hot-one,因为我会错过在别人订阅之前生成的元素
旁注:在我的代码中,我的映射没有任何清理机制,因此它会在某个时候产生异常,但现在这并不重要。如此简单。。。我不知道为什么我错过了这个漂亮的接线员: 因此,基本上删除整个
List/Map
部分代码,并使用replay()
而不是publish()
简化示例:
UnicastProcessor<String> processor = UnicastProcessor.create();
FluxSink<String> fluxSink = processor.sink(FluxSink.OverflowStrategy.LATEST);
//change 'publish()' to 'replay()'
Flux<String> hotFlux = processor.publish().autoConnect();
hotFlux.subscribe(n -> log.info("1st subscriber: {}", n));
fluxSink.next("one");
hotFlux.subscribe(n -> log.info("2nd subscriber: {}", n));
fluxSink.next("two");
使用replay()
进行输出:
只是想知道为什么不能使用像mongo这样的反应数据库?好问题。但答案很简单——这个存储库是真实系统模拟的一部分。我不想为了模拟的目的而在我的应用程序中添加更多需要单独维护的组件。然而,如果有任何反应式数据库的内存解决方案,我一定会尝试一下。有吗?
1st subscriber: one
1st subscriber: two
2nd subscriber: two
1st subscriber: one
2nd subscriber: one
1st subscriber: two
2nd subscriber: two