客户端从热流

时间:2018-04-03 13:49:33

标签: java spring spring-webflux reactor

我做了一个简单的春季启动应用程序。 我有一个REST端点,它返回当前时间的热流。

@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时,我得到的数据流如下:

  

数据:2018-04-03T13:20:38.313222100Z

     

数据:2018-04-03T13:20:39.311493500Z

     

数据:2018-04-03T13:20:40.310878800Z

     

...

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

  

java.io.IOException:已建立的连接已被主机中的软件中止

     

...

我已经尝试过捕捉它,但它已经被抓住了,并没有让它恢复到我的方法。

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

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

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

我最终采用了这种方法,不同之处在于我将它移动到了一个新类,这样它就可以从所有控制器处理这种类型的所有异常。

@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();
    }

}

1 个答案:

答案 0 :(得分:3)

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

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

例如:

@RestController
public class NowResource {
    ...

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