带有反应器的webflux在bodyToMono中不会打印异常

时间:2019-12-28 10:04:44

标签: spring-webflux

我希望map或doOnError都可以输出日志,但事实是两者都不这样做,这使得它们似乎都无法运行。如果bodyToMono抛出异常,该如何打印?

public Mono<ServerResponse> tryWebflux(ServerRequest request) {
        log.info("start controller");

        Mono bodyMono = request.bodyToMono(HashMap.class)
                .doOnError(e -> log.error("something wrong", e))
                .map(body -> {
                    log.info("in map");
                    return body;
                });
        bodyMono.log().subscribe(System.out::println);
        return ServerResponse.ok().build();
}

结果:

  [reactor-http-nio-2] reactor.util.Loggers$Slf4JLogger: onSubscribe(FluxMap.MapSubscriber)
  [reactor-http-nio-2] reactor.util.Loggers$Slf4JLogger: request(unbounded)
  [reactor-http-nio-2] reactor.util.Loggers$Slf4JLogger: onComplete()

1 个答案:

答案 0 :(得分:0)

我猜是因为这里有此行

bodyMono.log().subscribe(System.out::println);

您看到,在大多数情况下,您从未订阅过应用程序。订阅的是发起呼叫的那个,在大多数情况下,这是呼叫的客户端(前端,api的调用者等),您的服务器是发布者,并且您要在此服务器中构建一个事件链,基本上是一个接一个地做事。

通过在中间订阅,您正在中断事件链。

尝试:

public Mono<ServerResponse> tryWebflux(ServerRequest request) {
    return request.bodyToMono(HashMap.class)
            .doOnError(e -> log.error("something wrong", e))
            .map(body -> {
                log.info("in map");
                return body;
            }).log() // We log, chaining on as you did before
            .then(ServerResponse.ok().build()); 
            // Here we use the then() keyword to still keep chaining on the mono
}

永不中断事件链非常重要。如果您看到自己在中间订阅,则可能是做错了,除非您的应用程序是某事的发起者或“消费者”。