[英]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.deferContextual和Flux.deferContextual ,它們取代了 v3.3 中引入的Mono.deferWithContext和Flux.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.