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

Spring WebFlux中WebClient返回Mono<List<String>>填充Map为空问题

问题根源

你的代码里subscribe()是异步触发请求,但不会等待请求完成就直接返回map了,所以此时所有请求还在后台执行,map自然是空的。另外,用for循环手动处理每个订单号并调用subscribe也不是响应式编程的正确姿势。

正确实现方式

在Spring WebFlux中,应该用响应式操作符来组合异步任务,而不是手动管理异步流程。正确的做法是返回Mono<Map<String, List<String>>>,让调用方继续响应式处理:

public Mono<Map<String, List<String>>> getShipment(List<String> orderNums) {
    ParameterizedTypeReference<List<String>> LIST_TYPE_REF = new ParameterizedTypeReference<>() {};
    final String endpointUrl = "/the-path";
    final String queryParameter = "thequeryparam";

    return Flux.fromIterable(orderNums)
            // 每个订单号发起请求,返回订单号与对应List的Entry
            .flatMap(orderNo -> 
                this.client.get()
                        .uri(uriBuilder -> uriBuilder.path(endpointUrl)
                                .queryParam(queryParameter, orderNo)
                                .build())
                        .retrieve()
                        .bodyToMono(LIST_TYPE_REF)
                        // 将结果与订单号绑定成Entry
                        .map(list -> Map.entry(orderNo, list))
            )
            // 收集所有Entry成Map
            .collectMap(Map.Entry::getKey, Map.Entry::getValue);
}

关键说明

  • 响应式流处理:用Flux.fromIterable把订单列表转成响应式流,逐个处理每个订单号。
  • flatMap组合异步请求:每个订单号对应的WebClient请求是一个Mono,用flatMap把这些Mono合并到主流中。
  • collectMap收集结果:将每个订单号与对应结果的Entry收集成最终的Map,这个操作会等待所有请求完成后才返回完整的Mono<Map>。
  • 返回类型变更:方法返回Mono<Map>而不是直接返回Map,这是响应式编程的规范——异步操作的结果必须用Mono/Flux包裹,让调用方决定是继续响应式处理还是在合适的时机调用block()(仅在非WebFlux环境或初始化等场景建议使用block())。

如果必须返回同步Map(不推荐)

如果你的业务场景确实需要直接返回Map而非响应式类型,只能在最后调用block()等待所有请求完成,但要注意这会阻塞当前线程,违背WebFlux的非阻塞设计初衷:

public Map<String, List<String>> getShipment(List<String> orderNums) {
    ParameterizedTypeReference<List<String>> LIST_TYPE_REF = new ParameterizedTypeReference<>() {};
    final String endpointUrl = "/the-path";
    final String queryParameter = "thequeryparam";

    return Flux.fromIterable(orderNums)
            .flatMap(orderNo -> 
                this.client.get()
                        .uri(uriBuilder -> uriBuilder.path(endpointUrl)
                                .queryParam(queryParameter, orderNo)
                                .build())
                        .retrieve()
                        .bodyToMono(LIST_TYPE_REF)
                        .map(list -> Map.entry(orderNo, list))
            )
            .collectMap(Map.Entry::getKey, Map.Entry::getValue)
            // 阻塞等待所有请求完成
            .block();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:35:26