简体   繁体   English

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

[英]HTTP Response Exception Handling in Spring 5 Reactive

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. 我遇到了以下问题:我想处理从调用另一个REST服务收到的所有HTTP状态,并在收到一些错误的HTTP状态时抛出异常。 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 . 例如,当我调用端点并收到404 HTTP状态时,我想抛出一个异常,并在一些ExceptionHandler类中处理该异常,就像在Spring 4中使用@ControllerAdvice

What is the right way to do this? 这样做的正确方法是什么? Hope to receive some good suggestions. 希望收到一些好的建议。

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. 使用WebClient ,您可以从远程服务接收HTTP 404响应。 By default, all 4xx and 5xx client responses will be turned into WebClientResponseException . 默认情况下,所有4xx5xx客户端响应都将变为WebClientResponseException So you can directly handle those exceptions in your WebFlux app. 因此,您可以直接在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 ExchangeFilterFunction that you can set once and for all on a WebClient instance 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 ). 随着春天WebFlux与注释,您可以处理与注解的方法例外@ExceptionHandler (见Spring Framework的参考文档 )。

Note: using a WebExceptionHandler is 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. 注意:使用WebExceptionHandler是可能的,但它的级别很低,因为你没有高级支持:你需要手动编写带缓冲区的响应,而不需要任何序列化支持。

I think what you are looking for is WebFluxResponseStatusExceptionHandler the 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. 在WebHandler API中,WebExceptionHandler可用于处理来自WebFilter链和目标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. 使用WebFlux配置时,注册WebExceptionHandler就像将其声明为Spring bean一样简单,并可选择通过bean声明上的@Order或通过实现Ordered来表示优先级。

This example may 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.");
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM