簡體   English   中英

如何在 Reactor 中將 Context 與 flatMap() 一起使用?

[英]How to use Context with flatMap() in Reactor?

我在理解Context 時遇到問題。 所以文檔說Context是:

通過上下文協議在運算符等組件之間傳播的鍵/值存儲。 上下文非常適合傳輸正交信息,例如跟蹤或安全令牌。

偉大的。

現在讓我們假設我們想使用Context傳播一些東西,讓它無處不在。 要調用另一個異步代碼,我們只需使用flatMap()方法。

問題如何訪問被調用方法內的上下文?

示例(簡單)代碼:

public class TestFlatMap {
    public static void main(final String ...args) {
        final Flux<String> greetings = Flux.just("Hubert", "Sharon")
            .flatMap(TestFlatMap::nameToGreeting)
            .subscriberContext(context ->
                Context.of("greetingWord", "Hello")  // context initialized
            );
        greetings.subscribe(System.out::println);
    }

    private static Mono<String> nameToGreeting(final String name) {
        return Mono.just("Hello " + name + " !!!");  // ALERT: we don't have Context here
    }
}

被調用的方法可以(並且很可能會)在另一個類中。

提前感謝您的幫助!

編輯:刪除了一些代碼,使問題更加簡潔明了。

鏈接您的Publisher ,並且Context可能與您同在

在這種情況下,您連接了所有Publisher (並且這包括flatMap / concatMap和類似運算符中的連接),您將在整個流運行時之間正確傳播Context

要在nameToGreeting方法中訪問Context ,您可以調用Mono.subscribeContext並檢索存儲的信息事件(如果方法似乎不相關)。 以下顯示了上述概念:

public class TestFlatMap {
    public static void main(final String ...args) {
        final Flux<String> greetings = Flux.just("Hubert", "Sharon")
                                           .flatMap(TestFlatMap::nameToGreeting)
                                           .subscriberContext(context ->
                                                   Context.of("greetingWord", "Hello")  // context initialized
                                           );
        greetings.subscribe(System.out::println);
    }

    private static Mono<String> nameToGreeting(final String name) {
        return Mono.subscriberContext()
                   .filter(c -> c.hasKey("greetingWord"))
                   .map(c -> c.get("greetingWord"))
                   .flatMap(greetingWord -> Mono.just(greetingWord + " " + name + " " + "!!!"));// ALERT: we have Context here !!!
    }
}

此外,您可以使用zip運算符以下列方式執行相同操作,以便稍后合並結果:

public class TestFlatMap {
    public static void main(final String ...args) {
        final Flux<String> greetings = Flux.just("Hubert", "Sharon")
                                           .flatMap(TestFlatMap::nameToGreeting)
                                           .subscriberContext(context ->
                                                   Context.of("greetingWord", "Hello")  // context initialized
                                           );
        greetings.subscribe(System.out::println);
    }

    private static Mono<String> nameToGreeting(final String name) {
        return Mono.zip(
            Mono.subscriberContext()
                .filter(c -> c.hasKey("greetingWord"))
                .map(c -> c.get("greetingWord")), // ALERT: we have Context here !!!
            Mono.just(name),
            (greetingWord, receivedName) -> greetingWord + " " + receivedName + " " + "!!!"
        );
    }
}

那么,為什么它有效呢?

從上面的示例中可以看出, nameToGreeting是在主要Flux的上下文中調用的。 在引擎蓋下 - > (這里有一些FluxFlatMap內部) ,每個映射的Publisher都由FlatMapInner訂閱。 如果我們查看FlatMapInner並查找currentContext重寫,我們將看到, FlatMapInner使用父Context ,這意味着如果父有一個Reactor Context - 那么這個上下文將傳播到每個內部Publisher

因此,由nameToGreeting方法返回的Mono將具有與其父級相同的Context

Reactor-Core v3.4 引入了Mono.deferContextualFlux.deferContextual ,它們取代了 v3.3 中引入的Mono.deferWithContextFlux.deferWithContext

使用這些方法, Oleh Dokukas zip 示例可以簡化為

public class TestFlatMap {
    public static void main(final String ...args) {
        final Flux<String> greetings = Flux.just("Hubert", "Sharon")
                .flatMap(TestFlatMap::nameToGreeting)
                .subscriberContext(context ->
                        Context.of("greetingWord", "Hello"));  // context initialized
        greetings.subscribe(System.out::println);
    }

    private static Mono<String> nameToGreeting(final String name) {
        return Mono.deferContextual(c -> Mono.just(name)
                .filter(x -> c.hasKey("greetingWord"))
                .map(n -> c.get("greetingWord") + " " + n + " " + "!!!"));
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM