You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用getProductContract返回空列表,Mono未执行问题如何解决

问题根因

你当前的代码采用了命令式编程的写法拼接响应式流,存在两个核心错误:

  1. forEach中启动的getProductDetails、getProductContracts都是异步运行在boundedElastic线程池的任务,代码不会等待这些异步任务执行完成,就直接返回了还没被填充的resultList,所以拿到的永远是空列表。
  2. 你没有正确拼接响应式流的执行链,手动创建集合收集结果的写法在响应式场景下完全不适用,且你没有正确触发流的订阅(响应式流只有被订阅才会执行,Service层无需手动订阅,只要返回正确的流结构,最终会由Spring WebFlux框架在Controller层完成订阅)。

正确实现代码

修改后的Service.java代码如下:

// Service.java
public Mono<List<ProductContract>> getProductContract() {
    Set<String> productIdList = new HashSet<>();
    productIdList.add("p123");
    productIdList.add("p456");

    // 将每个productId转换为对应的查询流,合并为Flux统一管理
    return Flux.fromIterable(productIdList)
            // 异步查询每个product的详情,指定运行线程池
            .flatMap(productId -> prodRepository.getProductDetails(productId)
                    .subscribeOn(Schedulers.boundedElastic()))
            // 用详情返回的contractId查询对应合同列表
            .flatMap(productDetail -> prodRepository.getProductContracts(productDetail.getProductContractId()))
            // 取合同列表的第一个元素,自动过滤空值
            .mapNotNull(contracts -> contracts.stream().findFirst().orElse(null))
            // 所有查询完成后自动收集为List,包装为Mono返回
            .collectList()
            // 若需要打印结果大小可新增doOnNext操作
            .doOnNext(resultList -> log.info("size {}", resultList.size()));
}

逻辑说明

  • 用Flux.fromIterable把产品ID集合转换成响应式流,统一管理所有异步任务的执行生命周期
  • 所有异步查询的逻辑都拼接到同一个执行链中,框架订阅后会自动等待所有任务执行完成,再返回填充完成的结果列表
  • 无需手动创建集合、手动触发订阅,完全符合响应式编程的规范

内容的提问来源于stack exchange,提问作者sumit pramanik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 00:24:05