我在理解上下文时遇到问题。因此文档说 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
}
}
被调用的方法可以(并且很可能是)在另一个类中。
谢谢您的帮助!
编辑:删除了一些代码,以使问题更简洁明了。
答案 0 :(得分:2)
Publisher
,也许Context
与您同在在这种情况下,您连接了所有Publisher
(并且包括flatMap
/ concatMap
内的连接以及类似的运算符),Context
将会正确传播整个流运行时。
要使用Context
方法访问nameToGreeting
,如果方法似乎无关,则可以调用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
的上下文中被调用。在后台-> (Here Some FluxFlatMap internals)下,每个映射的Publisher
由FlatMapInner
订阅。如果我们查看FlatMapInner
并查找the currentContext
override,我们会看到FlatMapInner
使用父级Context
,这意味着父级是否有Reactor Context
-那么此上下文将传播到每个内部Publisher
。
因此,由nameToGreeting
方法Mono
返回的Context
将与其父对象相同
答案 1 :(得分:0)
Reactor-Core v3.4 引入了 Mono.deferContextual 和 Flux.deferContextual,它们取代了 v3.3 中引入的 Mono.deferWithContext 和 Flux.deferWithContext。
使用这些方法,Oleh Dokukas zip example 可以简化为
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 + " " + "!!!"));
}
}