Spring 5 Reactive 中的 HTTP 响应异常处理

我正在使用Spring Boot 2和Spring 5以及WebFlux反应式启动器开发一些反应式微服务。

我遇到了以下问题:我想处理从调用另一个REST服务中获得的所有HTTP状态,并在收到一些错误的HTTP状态时引发异常。例如,当我调用一个端点并收到一个 404 HTTP 状态时,我想引发一个异常,并且该异常要在某个 ExceptionHandler 类中处理,就像在 Spring 4 中使用 .@ControllerAdvice

正确的方法是什么?希望收到一些好的建议。


答案 1

这可以通过两个独立的部分来解决。

如何将 WebClient 收到的 HTTP 404 响应转换为自定义异常

使用 时,可以从远程服务接收 HTTP 404 响应。默认情况下,所有响应和客户端响应都将转换为 。因此,您可以在 WebFlux 应用程序中直接处理这些异常。WebClient4xx5xxWebClientResponseException

如果您只想将 404 响应转换为自定义异常,可以执行以下操作:

WebClient webClient = //...
webClient.get().uri("/persons/1")
  .retrieve()
  .onStatus(httpStatus -> HttpStatus.NOT_FOUND.equals(httpStatus),
                        clientResponse -> Mono.error(new MyCustomException()))
  .bodyToMono(...);

这显然是在每个客户端调用的基础上完成的。

您可以通过在以下实例上一劳永逸地设置的 ,以更可重用的方式实现相同的目标:ExchangeFilterFunctionWebClient

WebClient.builder().filter(myExchangeFilterFunction)...

如何处理 WebFlux 应用程序中的自定义异常

使用带有注释的Spring WebFlux,您可以使用带有注释的方法处理异常(请参阅Spring Framework参考文档)。@ExceptionHandler

注意:可以使用 a,但它的级别非常低,因为您将没有高级支持:您需要手动编写带有缓冲区的响应,而无需任何序列化支持。WebExceptionHandler


答案 2

我想你正在寻找的是检查这个作为参考WebFluxResponseStatusExceptionHandler

在 WebHandler API 中,WebExceptionHandler 可用于处理来自 WebFilter 链和目标 WebHandler 链的异常。使用 WebFlux 配置时,注册 WebExceptionHandler 就像将其声明为 Spring Bean 一样简单,并且可以选择通过 bean 声明上的@Order或通过实现 Ordered 来表示优先级。

这个例子可能会有所帮助,我自己还没有尝试过。

@Component
@Order(-2)
class RestWebExceptionHandler implements WebExceptionHandler{

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (ex instanceof PostNotFoundException) {
            exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);

            // marks the response as complete and forbids writing to it
            return exchange.getResponse().setComplete();
        }
        return Mono.error(ex);
    }
}

class PostNotFoundException extends RuntimeException {
    PostNotFoundException(String id) {
        super("Post:" + id + " is not found.");
    }
}