当客户端与热流断开连接时执行一些操作

Execute some action when client disconnects from hot stream

我制作了一个简单的 spring 启动应用程序。 我有一个 REST 端点 returns 当前时间的热门流。

@RestController
public class NowResource {

    @GetMapping(value = "/now", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> now() {
        return Flux.interval(Duration.ofSeconds(1))
            .flatMap(t -> Flux.just(Instant.now().toString()));
    }

}

当我调用 http://localhost:8080/now 时,我得到的数据流如下所示:

data:2018-04-03T13:20:38.313222100Z

data:2018-04-03T13:20:39.311493500Z

data:2018-04-03T13:20:40.310878800Z

...

当我断开与流的连接(关闭浏览器选项卡)时,抛出一个 IOException,捕获并打印堆栈跟踪。

java.io.IOException: An established connection was aborted by the software in your host machine

...

我试过捕捉它,但它已经被捕捉到,无法返回我的方法。

我尝试将 doOnTerminate()doOnError() 等添加到 Flux 但似乎没有任何效果,我猜实际事件是不同类型的。

我能否以某种方式访问​​此异常以不同于仅打印它来处理它? (我想避免在日志中输出 200 多行,而只打印“DONE”。)

编辑:我的解决方案基于 Tomas Pinos 的回答

我最终采用了这种方法,不同之处在于我将它移到了一个新的 class 并且这样它可以处理来自所有控制器的所有此类异常。

@Slf4j
@ControllerAdvice
class IOExceptionHandler implements WebExceptionHandler {

    @ExceptionHandler(IOException.class)
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        return Mono.just(ex.getMessage())
            .doOnNext(
                msg -> log.warn("IOException occurred: {}.", msg)
            )
            .then();
    }

}

异常与浏览器和控制器之间的 HTTP 连接处理有关(简单地说)。

它可以在控制器的 @ExceptionHandler 方法中处理(或者在 @ControllerAdvice class 中处理,如果你想在更多控制器上应用相同的异常处理)。

例如:

@RestController
public class NowResource {
    ...

    @ExceptionHandler(IOException.class)
    public void handleException(IOException e) {
        log.warn("IOException occurred: {}", e.getMessage());
    }
}