Делать несколько запросов с WebClient - PullRequest
0 голосов
/ 01 мая 2019

Итак, моя цель - использовать 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 Ответ

2 голосов
/ 01 мая 2019

Используйте .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.

...