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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49648435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 10:25:21  来源:igfitidea点击:

HTTP Response Exception Handling in Spring 5 Reactive

javaspring-bootexceptionspring-webflux

提问by Dina Bogdan

I'm developing some reactive microservices using Spring Boot 2 and Spring 5 with WebFlux reactive starter.

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

I'm facing the following problem: I want to handle all HTTP Statuses that I receive from calling another REST Services and throws an exception when I receive some bad HTTP Status. For example, when I call an endpoint and I receive an 404 HTTP Status, I want to throw an exception and that exception to be handled in some ExceptionHandler class, just like the way it was in Spring 4 with @ControllerAdvice.

我面临以下问题:我想处理通过调用另一个 REST 服务收到的所有 HTTP 状态,并在收到一些错误的 HTTP 状态时抛出异常。例如,当我调用端点并收到 404 HTTP 状态时,我想抛出一个异常,并且该异常将在某些 ExceptionHandler 类中处理,就像在 Spring 4 中使用@ControllerAdvice.

What is the right way to do this? Hope to receive some good suggestions.

这样做的正确方法是什么?希望得到一些好的建议。

回答by Brian Clozel

This can be addressed in two independent parts.

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

How to convert HTTP 404 responses received by WebClient into custom exceptions

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

When using WebClient, you can receive HTTP 404 responses from remote services. By default, all 4xxand 5xxclient responses will be turned into WebClientResponseException. So you can directly handle those exceptions in your WebFlux app.

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

If you'd like to turn only 404 responses into custom exceptions, you can do the following:

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

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

This is obviously done on a per client call basis.

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

You can achieve the same in a more reusable way with an ExchangeFilterFunctionthat you can set once and for all on a WebClientinstance like this:

您可以使用更可重用的方式实现相同的目的ExchangeFilterFunction,您可以在这样的WebClient实例上一劳永逸地设置它:

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

How to handle custom exceptions in WebFlux apps

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

With Spring WebFlux with annotations, you can handle exceptions with methods annotated with @ExceptionHandler(see Spring Framework reference documentation).

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

Note: using a WebExceptionHandleris possible, but it's quite low level as you'll have no high-level support there: you'll need to manually write the response with buffers without any support for serialization.

注意:使用 aWebExceptionHandler是可能的,但它是相当低级别的,因为您在那里没有高级支持:您需要手动编写带有缓冲区的响应,而不支持任何序列化。

回答by P?r Nilsson

I think what you are looking for is WebFluxResponseStatusExceptionHandlerthe check this for reference.

我认为您正在寻找的是WebFluxResponseStatusExceptionHandler检查此以供参考

In the WebHandler API, a WebExceptionHandler can be used to to handle exceptions from the chain of WebFilter's and the target WebHandler. When using the WebFlux Config, registering a WebExceptionHandler is as simple as declaring it as a Spring bean, and optionally expressing precedence via @Order on the bean declaration or by implementing Ordered.

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

This examplemay help, have not tried it myself.

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

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