java - 如何有条件地使用 "zipWhen"?

标签 java spring project-reactor spring-webflux

您好,我想知道如何使用reactor项目的“zipwhen”功能,因为文档中不清楚。

我的问题是,我对 Rest/Web 服务进行了一系列调用,问题是,正如我现在所拥有的那样,我总是调用所有服务,但我想参数化,以便在以下情况下不总是调用所有服务不依赖于使用 zipwhen 的需要。

我真的不知道是否可以使用 zipwhen。

类似于:

我有一个类服务,我在其中调用不同的 Web 服务(因为它是一个示例,所以它总是相同的,但实际上它将调用 n 个不同的 Web 服务)

@Service
public class FuenteRiesgoService {

    @Autowired
    SmartBearWsClient smartBearWsClient;

    public Mono<GetCurrentTimeResponse> fuenteWS1() {

        return Mono.fromCallable(() -> {
            Random rn = new Random();
            System.out.println("Llamando a fuente WS1 ..... on " + Thread.currentThread().getName());
            Thread.sleep(rn.nextInt(50 - 1 + 1) + 1 * 10000);
            GetCurrentTimeResponse getCurrentTimeResponse = smartBearWsClient.getCurrentTime(new GetCurrentTime());
            System.out.println("Respuesta fuente WS1 " + getCurrentTimeResponse.getGetCurrentTimeResult() + " on "
                    + Thread.currentThread().getName());
            return getCurrentTimeResponse;
        }).subscribeOn(Schedulers.parallel());

    }

    public Mono<GetCurrentTimeResponse> fuenteWS2(boolean call) {

        return Mono.fromCallable(() -> {
            Random rn = new Random();
            System.out.println("Llamando a fuente WS2 ..... on " + Thread.currentThread().getName());
            Thread.sleep(rn.nextInt(50 - 1 + 1) + 1 * 10000);
            GetCurrentTimeResponse getCurrentTimeResponse = smartBearWsClient.getCurrentTime(new GetCurrentTime());
            System.out.println("Respuesta fuente WS2 " + getCurrentTimeResponse.getGetCurrentTimeResult() + " on "
                    + Thread.currentThread().getName());
            return getCurrentTimeResponse;
        }).subscribeOn(Schedulers.parallel());

    }

public Mono<GetCurrentTimeResponse> fuenteWS3() {

    return Mono.fromCallable(() -> {
        Random rn = new Random();
        System.out.println("Llamando a fuente WS3 ..... on " + Thread.currentThread().getName());
        Thread.sleep(rn.nextInt(50 - 1 + 1) + 1 * 10000);
        GetCurrentTimeResponse getCurrentTimeResponse = smartBearWsClient.getCurrentTime(new GetCurrentTime());
        System.out.println("Respuesta fuente WS3 " + getCurrentTimeResponse.getGetCurrentTimeResult() + " on "
                + Thread.currentThread().getName());
        return getCurrentTimeResponse;
    }).subscribeOn(Schedulers.parallel());

}

public Mono<GetCurrentTimeResponse> fuenteWS4() {

    return Mono.fromCallable(() -> {
        Random rn = new Random();
        System.out.println("Llamando a fuente WS4 ..... on " + Thread.currentThread().getName());
        Thread.sleep(rn.nextInt(50 - 1 + 1) + 1 * 10000);
        GetCurrentTimeResponse getCurrentTimeResponse = smartBearWsClient.getCurrentTime(new GetCurrentTime());
        System.out.println("Respuesta fuente WS4 " + getCurrentTimeResponse.getGetCurrentTimeResult() + " on "
                + Thread.currentThread().getName());
        return getCurrentTimeResponse;
    }).subscribeOn(Schedulers.parallel());

}

}

通过此返回,它的作用是始终调用 4 个 Web 服务

return fuenteRiesgoService.fuenteWS1()
    .zipWith(fuenteRiesgoService.fuenteWS2(), (a, b) -> {
    return " - WS1 : " + a.getGetCurrentTimeResult().toString() + " - WS2 : "
                + b.getGetCurrentTimeResult().toString();
}).zipWith(fuenteRiesgoService.fuenteWS3(), (a, b) -> {
    return a + " - WS3 : " + b.getGetCurrentTimeResult().toString();
}).zipWith(fuenteRiesgoService.fuenteWS4(), (a, b) -> {
    System.out.println("Fuentes obtenidas " + a + " - WS4 : " + b.getGetCurrentTimeResult().toString()
                + " on " + Thread.currentThread().getName());
    return a + " - WS4 : " + b.getGetCurrentTimeResult().toString();
});

但是我想做的是能够用zipwhen不通过参数来调用自己和别人。

例如,调用 ws2 和 ws4 但不调用 ws3,因此它不会对 ws3 执行任何操作

boolean callws2 = true;
boolean callws3 = false;
boolean callws4 = true;

return fuenteRiesgoService.fuenteWS1()
    .zipWhen(if(callws2 = true) -> fuenteRiesgoService.fuenteWS2(), (a, b) -> {
    return " - WS1 : " + a.getGetCurrentTimeResult().toString() + " - WS2 : "
                + b.getGetCurrentTimeResult().toString();
}).zipWhen(if(callws3 = true) -> fuenteRiesgoService.fuenteWS3(), (a, b) -> {
    return a + " - WS3 : " + b.getGetCurrentTimeResult().toString();
}).zipWhen(if(callws4 = true) -> fuenteRiesgoService.fuenteWS4(), (a, b) -> {
    System.out.println("Fuentes obtenidas " + a + " - WS4 : " + b.getGetCurrentTimeResult().toString()
                + " on " + Thread.currentThread().getName());
    return a + " - WS4 : " + b.getGetCurrentTimeResult().toString();
});

最佳答案

Project Reactor 提供了许多运算符,有时很难找出哪个是最佳解决方案 - 函数式、响应式思维模式与此有很大关系。

zipWhen 是一个组合结果的特定运算符,但与 zipWith 不同,您需要先查看第一个结果,然后才能进行第二次调用。我们举个例子:准备假期。您需要先预订酒店,然后才能预订出租车前往那里。

Mono<HotelBooking> first = bookHotel(startDate, EndDate);
// you need the chosen hotel location before you can book a taxi,
// but you still need both bookings in the end
Mono<Tuple2<HotelBooking, TaxiBooking>> result = first
    .zipWhen(booking -> bookTaxi(airport, booking.getLocation());

看来您的示例不需要您从中间结果中获取信息。如果逻辑是同步且非阻塞的,则常规应用程序逻辑应该是首选方式。

Mono<String> result = fuenteRiesgoService.fuenteWS1();
if (callws2) {
  result = result.zipWith(fuenteRiesgoService.fuenteWS2(), combinatorFunction);
}
if (callws3) {
  result = result.zipWith(fuenteRiesgoService.fuenteWS3(), combinatorFunction);
}
return result;

关于java - 如何有条件地使用 "zipWhen"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48803609/

相关文章:

java - 一对多删除关联

java - 如何移动 xmlns :xs and xmlns:xsi to Root Element with JAXB?

java - react 堆重试不调用要重试的方法

spring-boot - 如何并行调用多个Spring Webclient并等待结果?

java - 如何使用 Spring WebFlux Reactive 方式在处理函数中使用 Mono 和 Flux

Java 卡 RSAPrivateCrtKey 私有(private)指数 "d"

java - 从UTF8获取语言

javascript - 后台有 mysql 数据库的 Spring 应用程序的 ICD 10 下拉列表

java - Spring data Elasticsearch 按字段查找和最新日期查询

java - Spring Boot入门404错误