我们怎样才能将@ExceptionHandler与spring web flux结合使用?

时间:2018-03-06 18:02:50

标签: java spring spring-webflux exceptionhandler

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

我尝试将此注释与web-flux控制器一起使用,它仍然适用于我,但经过一些调查后我发现here

  

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

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

更新: 从spring.io来看,它似乎得到了支持,但仍然缺乏一般性的理解

谢谢,

3 个答案:

答案 0 :(得分:6)

您可以使用@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合同中预期的错误信号发送(有关详细信息,请参阅the "error handling" documentation section)。

答案 1 :(得分:2)

不是原始问题的确切答案,但是将异常映射到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\""
}

答案 2 :(得分:2)

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

示例:

  1. 添加 webflux 依赖

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

@RestControllerAdvice 公共类 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();
}

}

  1. 创建控制器

    @GetMapping(value = "/error",produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 公共单声道异常返回(){ return Mono.error(new RuntimeException("test error")); }

此处提取的示例:

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