Spring 2.0 WebFlux: объединить несколько Mono <String>, где строка представляет собой json, преобразованный в строку, в один поток <String> - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть три строки Mono of JSON, как показано ниже

Mono<String> strInventoryResp=invWebClient.get().
            uri("/findATSInventory?skuId="+skuId).
            exchange().flatMap(resp-> resp.bodyToMono(String.class));


    Mono<String> strProductResponse=productClient.get().
            uri("/v2/products/id/"+skuId).
            exchange().flatMap(resp-> resp.bodyToMono(String.class));


    Mono<String> strItemResp=productClient.get().
            uri("/v2/items?id="+skuId).
            exchange().flatMap(resp-> resp.bodyToMono(String.class));

Я хочу объединить ее в строку Flux of Json так, чтобы в результате получилась также строка JSON.

У меня естьпробовал статический метод Flux.merge, но, очевидно, он не возвращает в формате json, как показано ниже

Flux.merge(strProductResponse,strItemResp,strInventoryResp);

Как мне вернуть поток комбинированных моно-ответов, так что верный поток строки JSON возвращается вбраузер, когда я вызываю контроллер, вызывающий этот метод?

РЕДАКТИРОВАТЬ: Моя проблема заключается в том, чтобы асинхронно вызывать эти три API с помощью веб-потока и объединить результат в один.Контроллер вызывает этот метод и возвращает объединенные результаты для пользовательского интерфейса.Есть ли альтернативный подход к этому?

Ответы [ 2 ]

0 голосов
/ 18 декабря 2018

Еще одно решение, подобное Пиотру, но с reduce, ломбоком и неизменным агрегатором.

@Test
public void test() {
    Mono<String> strInventoryResp = Mono.just("strInventoryResp");
    Mono<String> strProductResponse = Mono.just("strProductResponse");
    Mono<String> strItemResp = Mono.just("strItemResp");

    Mono<Aggregator> result = Flux.merge(
            strInventoryResp.map(s -> Aggregator.builder().strInventoryResp(s).build()),
            strItemResp.map(s -> Aggregator.builder().strItemResp(s).build()),
            strProductResponse.map(s -> Aggregator.builder().strProductResponse(s).build()))
            .reduce((aggregator, aggregator2) -> aggregator.toBuilder()
                    .strInventoryResp(Optional.ofNullable(aggregator2.strInventoryResp)
                            .orElseGet(() -> aggregator.strInventoryResp))
                    .strProductResponse(Optional.ofNullable(aggregator2.strProductResponse)
                            .orElseGet(() -> aggregator.strProductResponse))
                    .strItemResp(Optional.ofNullable(aggregator2.strItemResp)
                            .orElseGet(() -> aggregator.strItemResp))
                    .build());

    //now you have Mono with filled Aggregator and you can make your json result
}

@Builder(toBuilder = true)
private static class Aggregator {
    private final String strInventoryResp;
    private final String strProductResponse;
    private final String strItemResp;
}

И у меня есть уведомление о вашем примере.Похоже, у вас есть несколько веб-клиентов.И это плохая практика.Вы должны предпочесть один веб-клиент для приложения из-за использования потоков (несколько веб-клиентов создадут много потоков)

0 голосов
/ 17 декабря 2018

Вот как бы я решил это.

@Test
public void buildResponse() {
    final Mono<String> customerName = Mono.just("customer name");
    final Mono<String> customerPreference = Mono.just("customer preference");
    final Mono<String> cusomterShippingInformation = Mono.just("cusomter shipping information");

    final Mono<JsonObjectYouWantToReturn> returnThisAsAResponse = customerName
            .map(Builder::new)
            .zipWith(customerPreference)
            .map(t -> t.getT1().withCustomerPreference(t.getT2()))
            .zipWith(cusomterShippingInformation)
            .map(t -> t.getT1().withCustomerShippingInformation(t.getT2()))
            .map(Builder::build);

}

private class Builder {
    private String customerName;
    private String customerPreference;
    private String customerShippingInfo;

    public Builder(String customerName) {
        this.customerName = customerName;
    }

    public Builder withCustomerPreference(String customerPreference) {
        this.customerPreference = customerPreference;
        return this;
    }

    public Builder withCustomerShippingInformation(String t3) {
        this.customerShippingInfo = t3;
        return this;
    }


    public JsonObjectYouWantToReturn build() {
        return new JsonObjectYouWantToReturn(customerName, customerPreference, customerShippingInfo);
    }
}

private class JsonObjectYouWantToReturn {

    public final String customerName;
    public final String customerPreference;
    public final String customerShippingInfo;


    public JsonObjectYouWantToReturn(String customerName, String customerPreference, String customerShippingInfo) {
        this.customerName = customerName;
        this.customerPreference = customerPreference;
        this.customerShippingInfo = customerShippingInfo;
    }
}
...