Spring Reactive-重用Mono值

时间:2018-09-26 11:31:46

标签: java spring spring-webflux project-reactor

我有一系列使用Mono的{​​{1}}转换。我设法将生产代码简化为该测试用例:

flatMap

此打印:

@Test
public void test() {
    AtomicInteger iCounter = new AtomicInteger(1);
    Mono<String> iValueMono = Mono.fromSupplier(() -> {
        int iValue = iCounter.getAndIncrement();
        System.out.println("iValueMono CALL: " + iValue);
        return String.valueOf(iValue);
    });

    Mono<String> resultMono = Mono.just("X")
            .flatMap(append(iValueMono))
            .flatMap(append(iValueMono));

    StepVerifier.create(resultMono)
            .consumeNextWith(result -> assertThat(result).isEqualTo("X11"))
            .expectComplete()
            .verify();
}

private Function<String, Mono<String>> append(Mono<String> sMono) {
    return s -> sMono.map(v -> s + v);
}

我以为-我现在看到这是不正确的-每次我在iValueMono CALL: 1 iValueMono CALL: 2 org.junit.ComparisonFailure: Expected :"X11" Actual :"X12" 调用中映射iValueMono时,供应商都会重新执行以产生新的价值。我无法更改生产代码中append()的实现方式(例如,使其有状态地存储值)。如何实现此方法,以便仅调用一次价值提供者,并得到最终结果“ X11”?

当然,我对一种无阻塞,反应式的方法感兴趣。

2 个答案:

答案 0 :(得分:1)

使用Mono.cache()是答案:

  

将此Mono转换为热源,并缓存最后发出的信号以供进一步的订户使用。

使用它:

Mono<String> iValueMono = Mono.fromSupplier(() -> {
    int iValue = iCounter.getAndIncrement();
    System.out.println("iValueMono CALL: " + iValue);
    return String.valueOf(iValue);
}).cache();

提供仅一次致电供应商的预期结果。

答案 1 :(得分:0)

我重新编写了您的测试,现在iValueMono仅在出现一次时执行:

@Test
public void test() {
    AtomicInteger iCounter = new AtomicInteger(0);
    Mono<String> iValueMono = getMono(iCounter.incrementAndGet());

    Mono<String> resultMono = Mono.just("X")
        .flatMap(append(iValueMono))
        .flatMap(append(iValueMono));

    StepVerifier.create(resultMono)
        .consumeNextWith(result -> assertEquals(result, "X11"))
        .expectComplete()
        .verify();
}

private Mono<String> getMono(int x) {
    System.out.println("Called");
    return Mono.just(String.valueOf(x));
}

您怎么看?有帮助吗?