我制作了一个简单的 spring boot 应用程序。 我有一个返回当前时间的热流的 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
时,我得到的数据流如下所示:
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
...
我已经 try catch 它,但它已经被捕获并且没有返回到我的方法。
我尝试将 doOnTerminate()
、doOnError()
等添加到 Flux 但似乎没有任何效果,我猜实际事件是一种不同的类型。
我能否以某种方式访问此异常以不同于仅打印它来处理它? (我想避免在日志中输出 200 多行,而是打印“DONE”。)
编辑:我的解决方案基于 Tomas Pinos 的回答
我最终采用了这种方法,不同之处在于我将它移到了一个新类中,这样它就可以处理来自所有 Controller 的所有此类异常。
@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();
}
}
最佳答案
异常与浏览器和 Controller 之间的 HTTP 连接处理有关(简单地说)。
它可以在 Controller 的 @ExceptionHandler
方法中处理(或者在 @ControllerAdvice
类中处理,如果你想在更多 Controller 上应用相同的异常处理)。
例如:
@RestController
public class NowResource {
...
@ExceptionHandler(IOException.class)
public void handleException(IOException e) {
log.warn("IOException occurred: {}", e.getMessage());
}
}
关于java - 当客户端与热流断开连接时执行一些操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49631803/