【问题标题】:@ExceptionHandler called *after* finally block in Spring @RestController@ExceptionHandler 调用 *after* finally 在 Spring @RestController 中阻塞
【发布时间】:2017-10-30 15:43:34
【问题描述】:

我正在使用 Spring Boot 1.5.7.RELEASE 创建一个 REST API。我的控制器验证传入数据并引发 MyRequestValidationException。这是由@ExceptionHandler 处理的。

但是在测试我的代码时,我发现 @ExceptionHandler 在 finally {} 块之后被调用

这是预期的行为,还是我做错了什么? finally 块不应该是最后调用的东西吗?

@RestController
public class MyAPI {
@RequestMapping(value = "/login")
public AuthenticationResponse authenticationRequest(HttpServletRequest servletRequest, @RequestBody AuthenticationRequest authenticationRequest)  {
    long startTime = System.currentTimeMillis();
    try {
        this.logStartAPI(servletRequest, authenticationRequest);
        ThreadLocalStaticClass.getThreadLocalHttpStatus().set(HttpStatus.OK);

        .
        .
        .

        // This throws a Runtime exception RequestValidationException
        authenticationRequest.validate();

        .
        .
    } finally {
        this.logEndAPI(servletRequest, startTime, ThreadLocalStaticClass.getThreadLocalHttpStatus().get());
        ThreadLocalStaticClass.getThreadLocalHttpStatus().remove();
    }
}

这是我的 ExceptionHandler(在 @ControllerAdvice 类中)。

@ExceptionHandler(value = { MyRequestValidationException.class })
protected ResponseEntity<Object> handleMyRequestValidationException(RuntimeException ex, WebRequest request) {
    logger.error("RequestValidationException", ex);
    ThreadLocalStaticClass.getThreadLocalHttpStatus().set(HttpStatus.BAD_REQUEST);
    return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}

【问题讨论】:

  • throwing 代码中的finally 块之前如何调用它?
  • Spring MVC 将@ExceptionHandler 方法注册为ExceptionHandler。在调用您的 @RequestMapping 处理程序方法后,它会检查它是否引发了异常。如果确实如此,它会尝试查找并使用可以处理它的ExceptionHandler。到那时,执行已经离开了处理方法代码。 Spring 不会在任何它想要的地方注入代码。

标签: spring spring-mvc spring-boot


【解决方案1】:

@ExceptionHandler 就像 try-catch 在你的所有方法中一样,它的工作方式类似于:

@RestController
public class MyAPI {
@RequestMapping(value = "/login")
public AuthenticationResponse authenticationRequest(HttpServletRequest servletRequest, @RequestBody AuthenticationRequest authenticationRequest)  {
try {
    long startTime = System.currentTimeMillis();
    try {
        this.logStartAPI(servletRequest, authenticationRequest);
        ThreadLocalStaticClass.getThreadLocalHttpStatus().set(HttpStatus.OK);

        .
        .
        .

        // This throws a Runtime exception RequestValidationException
        authenticationRequest.validate();

        .
        .
    } finally {
        this.logEndAPI(servletRequest, startTime, ThreadLocalStaticClass.getThreadLocalHttpStatus().get());
        ThreadLocalStaticClass.getThreadLocalHttpStatus().remove();
    }
} catch(MyRequestValidationException e) {
   //handling of your exception
}
}

所以现在我想你明白你为什么会有这样的行为了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-27
    • 2014-08-29
    • 2011-10-07
    • 2019-07-18
    • 1970-01-01
    • 2020-10-09
    • 2013-11-16
    • 1970-01-01
    相关资源
    最近更新 更多