Spring Boot 3.x WebFlux:如何将循环中Mono<String>转为List<String>
解决Spring WebFlux中合并Mono为List的问题
原代码的问题
- Flux是不可变对象,
IdFlux.concat(IdMono1)会返回一个新的Flux实例,你没有将这个新实例赋值给IdFlux,导致原IdFlux始终是空的。 - 使用
parallelStream().forEach()结合响应式操作是错误的:响应式操作是异步非阻塞的,forEach的同步遍历无法正确追踪异步操作的完成状态,还会破坏响应式流的链式调用逻辑。 - 你定义的
Flux<Mono<String>>是嵌套的响应式类型,最终需要的是直接包含字符串的Flux<String>,再转换为List。
正确实现方式
响应式非阻塞写法(推荐)
直接将keySet转换为Flux,通过flatMap展开每个Mono<String>为字符串流,最后收集为List:
// 将keySet转为Flux,基于响应式流处理每个key Flux<String> idFlux = Flux.fromIterable(matchesByComp.keySet()) // flatMap自动将Mono<String>展开为Flux的元素,支持并行处理Redis请求 .flatMap(key -> reactiveRedisOperations.get(key, id)); // 收集所有字符串为List,返回Mono<List<String>> Mono<List<String>> idListMono = idFlux.collectList(); // 在WebFlux Controller中可直接返回Mono<List<String>>,框架会自动处理订阅和响应 // return idListMono;
同步获取List(仅允许阻塞的场景使用)
如果必须同步获取List(比如测试代码、非WebFlux主线程),可以使用block()方法(注意:WebFlux应用主线程中使用block会阻塞线程,违背响应式设计原则):
List<String> idList = idListMono.block();
额外说明
- 如果需要顺序处理每个Redis请求(而非并行),可以将
flatMap替换为concatMap,但concatMap是串行执行,性能会低于flatMap。 - 永远不要在WebFlux的请求处理线程中使用
block(),否则会耗尽线程池资源,导致应用性能急剧下降。
内容的提问来源于stack exchange,提问作者Amulya M
相关产品推荐
相关产品推荐

