Java中如何不使用block方法将Mono<List<Object>>转换为List<Object>
解决方案说明
核心认知
响应式编程中Mono<T>是异步计算结果的容器,结果未完成计算时不会存储真实的T实例,不存在非阻塞的方式直接从Mono<List<Address>>中取出同步的List<Address>实例。
不同场景处理方案
场景1:可以调整方法返回类型(推荐)
如果没有强绑定的同步返回要求,直接返回Mono<List<Address>>给上层调用方即可,上层可以通过响应式操作符处理后续逻辑,不需要主动取出List:
// 方法返回类型改为Mono<List<Address>> public Mono<List<Address>> getAddressList() { PagePublisher<Address> someAddressPage = someService.getPagePublisherForAddress(); return Flux.from(someAddressPage.items()).collectList(); } // 对List做操作的示例,用map运算符即可,不需要flatMap public Mono<List<AddressVO>> convertToVOList() { return getAddressList() .map(addressList -> addressList.stream() .map(AddressVO::new) .toList() ); }
如果是Spring Web/Flux环境,Controller直接返回Mono/Flux类型即可,框架会自动订阅并返回结果给前端,不需要自己转同步List。
场景2:方法必须返回List<Address>
这种场景下只能使用block()方法阻塞等待异步结果返回,没有其他替代方案。需要注意不要在响应式IO线程池中调用block(),避免阻塞核心线程,可以切换到业务弹性线程池执行:
public List<Address> getSyncAddressList() { PagePublisher<Address> someAddressPage = someService.getPagePublisherForAddress(); return Flux.from(someAddressPage.items()) .collectList() // 切换到弹性业务线程池执行,避免阻塞响应式核心线程 .subscribeOn(Schedulers.boundedElastic()) .block(); }
flatMap不生效的原因说明
flatMap运算符的作用是将Mono<T>中的元素转换为另一个Publisher<R>,用来做异步流的拼接,不是用来提取同步值的,和你的需求场景不匹配,所以无法实现预期效果。
内容的提问来源于stack exchange,提问作者Muhammad Umer
相关产品推荐
相关产品推荐

