使用 Spring WebClient 发出多个请求

Posted

技术标签:

【中文标题】使用 Spring WebClient 发出多个请求【英文标题】:Making multiple requests with Spring WebClient 【发布时间】:2019-09-19 18:47:22 【问题描述】:

所以我的目标是使用 WebClient 发出多个并发请求,等到它们全部完成,然后合并结果。这是我目前所拥有的:

...

Flux<ServerResponse> feedResponses = request
        .bodyToMono(AddFeedRequestDto.class)
        .map(AddFeedRequestDto::getFeeds) // Returns a list of RSS feed URLs
        .map(this::getServerResponsesFromUrls) // Returns a list of Mono<Feed>
        .map(Flux::merge) // Wait til all requests are completed
        // Not sure where to go from here

...

/** Related methods: **/

private List<Mono<Feed>> getServerResponsesFromUrls(List<String> feedUrls) 
    List<Mono<Feed>> feedResponses = new ArrayList<>();
    feedUrls.forEach(feedUrl -> feedResponses.add(getFeedResponse(feedUrl)));
    return feedResponses;


public Mono<Feed> getFeedResponse(final String url) 
    return webClient
            .get()
            .uri(url)
            .retrieve()
            .bodyToMono(String.class) // Ideally, we should be able to use bodyToMono(FeedDto.class)
            .map(this::convertResponseToFeedDto)
            .map(feedMapper::convertFeedDtoToFeed);


/** Feed.java **/
@Getter
@Setter
public class Feed 
    List<Item> items;

基本上,我的目标是将每个提要中的所有项目组合在一起,以创建一个统一的提要。但是,我不太确定在调用 Flux::merge 后该做什么。任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

使用.flatMap 代替.map / Flux.merge,如下所示:

Mono<Feed> unifiedFeedMono = request
        .bodyToMono(AddFeedRequestDto.class)  // Mono<AddFeedRequestDto>
        .map(AddFeedRequestDto::getFeeds)     // Mono<List<String>> feedUrls
        .flatMapMany(Flux::fromIterable)      // Flux<String> feedUrls
        .flatMap(this::getFeedResponse)       // Flux<Feed>
        .map(Feed::getItems)                  // Flux<List<Item>>
        .flatMap(Flux::fromIterable)          // Flux<Item>
        .collectList()                        // Mono<List<Item>>
        .map(Feed::new);                      // Mono<Feed>

请注意,.flatMap 是异步操作,将并行执行请求。如果你想限制并发,有一个重载版本需要 concurrency 参数。

.flatMap 无法保证顺序,并且生成的项目可能会交错。如果您需要更多订购保证,请替换为.concatMap.flatMapSequential

【讨论】:

排序不是问题,所以这个解决方案成功了。谢谢!

以上是关于使用 Spring WebClient 发出多个请求的主要内容,如果未能解决你的问题,请参考以下文章

Spring webclient exchangeToFlux()不发出HTTP请求

如何并行进行多个 Spring Webclient 调用并等待结果?

如何使用Spring WebClient同时进行多个调用?

如何使用 Spring WebClient 同时进行多个调用?

使用带有阻塞/同步请求的 Spring WebClient 使用 try/catch 捕获异常

Spring WebFlux WebClient - 如何解决 400 错误请求