在doOnSubscribe,doOnSuccess和doOnError中获取Reactor订阅者上下文

时间:2018-08-21 08:30:06

标签: spring-boot project-reactor

我正在尝试实现Reactor订户上下文(http://projectreactor.io/docs/core/release/reference/#context),以便可以将SLF4J MDC中的值传递到Flux中,然后在其中使用这些值进行记录。

我使用SubscriberContext()方法设置值,例如:

someFlux().subscriberContext(Context.of(MDC_ATTRIBUTE, MDC.get(MDC_ATTRIBUTE)));

我也可以访问链中的上下文。例如,使用flatMap:

.flatMap(r -> Mono.subscriberContext().map(ctx -> {
    String name = ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "NO CTX");
    return r;
}))

doOnEach()也可以工作:

.doOnEach(signal -> {
    Context ctx = signal.getContext();
    if (signal.isOnNext()) {
        try (MDC.MDCCloseable closeable = MDC.putCloseable(MDC_ATTRIBUTE_NAME, ctx.getOrDefault(MDC_ATTRIBUTE_NAME, "MAAAAN"))) {
            log.debug("FINISHED: {}", requestName);
        }
    }
})

只有一个问题。我想在doOnSubscribedoOnErrordoOnSuccess中记录一些内容。虽然我可以使用doOnEach检查signal.isOnNext()signal.isOnComplete(),但发现从未调用过signal.isOnSubscribe()

因此,问题是:我如何在doOnSubscribe()中获取上下文,或者这根本不可能?

1 个答案:

答案 0 :(得分:1)

有可能,但并非在100%的用例中,都有一些技巧:

Flux.just("foo")
    .doOnSubscribe(sub -> {
        Scannable actual = Scannable.from(sub).scan(Scannable.Attr.ACTUAL);
        if (actual instanceof CoreSubscriber) {
            Context context = ((CoreSubscriber) actual).currentContext();

            System.out.println(context);
        }
    })
    .map(v -> "value: " + v) //below or above doOnSubscribe is fine
    .subscriberContext(Context.of("foo", "bar")) //MUST be below doOnSubscribe
    .blockLast();