13

在 Spring Web 中,我们可以使用注解 @ExceptionHandler 来处理控制器的服务器和客户端错误。

我尝试将此注释与 web-flux 控制器一起使用,它仍然对我有用,但经过一番调查,我在这里发现了

Spring Web Reactive 的情况更加复杂。因为反应流是由与执行控制器方法的线程不同的线程评估的,所以异常不会自动传播到控制器线程。这意味着@ExceptionHandler 方法仅适用于直接处理请求的线程中抛出的异常。如果我们想使用@ExceptionHandler 特性,流中抛出的异常必须传播回线程。这似乎有点令人失望,但在撰写本文时 Spring 5 仍未发布,因此错误处理可能仍然会变得更好。

所以我的问题是如何将异常传播回线程。有没有关于使用 @ExceptionHandler 和 Spring web Flux 的好例子或文章?

更新:从spring.io看起来它是受支持的,但仍然缺乏一般的理解

谢谢,

4

3 回答 3

11

您可以使用@ExceptionHandler带注释的方法来处理在执行 WebFlux 处理程序(例如,您的控制器方法)中发生的错误。使用 MVC,您确实还可以处理映射阶段发生的错误,但 WebFlux 并非如此。

回到您的异常传播问题,您分享的文章不准确。

在反应式应用程序中,请求处理确实可以随时从一个线程跳到另一个线程,因此您不能再依赖“每个请求一个线程”模型(想想:)ThreadLocal

实际上,您不必考虑异常传播或如何管理线程。例如,以下示例应该是等效的:

@GetMapping("/test")
public Mono<User> showUser() {
  throw new IllegalStateException("error message!");
}


@GetMapping("/test")
public Mono<User> showUser() {
  return Mono.error(new IllegalStateException("error message!"));
}

Reactor 将按照 Reactive Streams 合约中的预期将这些异常作为错误信号发送(有关详细信息,请参阅“错误处理”文档部分)。

于 2018-03-06T20:22:28.273 回答
8

现在可以在 Spring WebFlux@ExceptionHandler@RestControllerAdvice甚至@ControllerAdvice在 Spring WebFlux 中使用。

例子:

  1. 添加 webflux 依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
  2. 创建你的类 ExceptionHandler

    @RestControllerAdvice
    public class ExceptionHandlers {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlers.class);
    
        @ExceptionHandler(Exception.class)
        @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
        public String serverExceptionHandler(Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return ex.getMessage();
        }
    }
    
  3. 创建控制器

    @GetMapping(value = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public Mono<String> exceptionReturn() {
        return Mono.error(new RuntimeException("test error"));
    }
    

此处提取的示例:

https://ddcode.net/2019/06/21/spring-5-webflux-exception-handling/

于 2021-02-09T22:18:28.583 回答
5

不是对原始问题的确切答案,但是将异常映射到 http 响应状态的快速方法是抛出org.springframework.web.server.ResponseStatusException/或创建自己的子类...

完全控制 http 响应状态 + spring 将添加一个带有选项的响应主体添加一个reason.

{
    "timestamp": 1529138182607,
    "path": "/api/notes/f7b.491bc-5c86-4fe6-9ad7-111",
    "status": 400,
    "error": "Bad Request",
    "message": "For input string: \"f7b.491bc\""
}
于 2018-06-17T22:01:09.470 回答