@ExceptionHandler在Spring @RestController中调用* after * finally块之后

时间:2017-10-30 15:43:35

标签: spring spring-mvc spring-boot

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

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

这是预期的行为,还是我做错了什么?不应该将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);
}

1 个答案:

答案 0 :(得分:2)

@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
}
}

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