在Spring中自定义@ControllerAdvice以进行异常处理

时间:2018-05-24 08:48:23

标签: java spring rest exception spring-restcontroller

我正在尝试将我的其他控制器中的异常映射到具有正文的响应,并在中心位置执行。

我试过这个:

@Order(Ordered.HIGHEST_PRECEDENCE)
@ControllerAdvice
public class RestErrorResponseExceptionHandler extends ResponseEntityExceptionHandler {
    @Override
    protected ResponseEntity<Object> handleExceptionInternal(
        Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
        super.handleExceptionInternal(ex, body, headers, status, request);

        return ResponseEntity.status(status).body(Error.from(status));
    }
} 

问题是永远不会触发处理程序。

如果我在其余控制器中使用@ExceptionHandler定义自定义方法,或扩展具有@ExceptionHandler的内容,那么一切正常,但这会引入一些糟糕的设计。

据我所知,Spring将首先尝试在控制器中查找异常处理方法,然后检查注册的处理程序。

我正在尝试通过WebMvcTest验证行为,而我得到的回复并不是我期待的错误对象。

我有什么遗失的吗?

3 个答案:

答案 0 :(得分:2)

ControllerAdvice是一个必须由Spring注册的配置。您必须在配置包中移动您的类,或者您可以通过注释注册它。

在我的情况下,我使用像这样的controllerAdvice:

@ControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(MyException.class) 
    public ResponseEntity<String> reponseMyException(Exception e) {
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body("my message");
    }
}

答案 1 :(得分:2)

Spring Framework提供了以下方法来帮助我们实现强大的异常处理。

  1. 基于控制器 - 我们可以在控制器类中定义异常处理程序方法。我们所需要的只是使用@ExceptionHandler注释来注释这些方法。此批注将Exception类作为参数。因此,如果我们为Exception类定义了其中一个,那么我们的请求处理程序方法抛出的所有异常都将被处理。 这些异常处理程序方法就像其他请求处理程序方法一样,我们可以构建错误响应并响应不同的错误页面。我们还可以发送JSON错误响应,我们将在后面的示例中查看。 如果定义了多个异常处理程序方法,则使用最接近Exception类的处理程序方法。例如,如果我们为IOException和Exception定义了两个处理程序方法,并且我们的请求处理程序方法抛出IOException,那么将执行IOException的处理程序方法。

  2. 全局异常处理程序 - 异常处理是一个贯穿各领域的问题,应该对我们应用程序中的所有切入点进行处理。我们已经研究过Spring AOP,这就是为什么Spring提供@ControllerAdvice注释,我们可以使用它来定义我们的全局异常处理程序。 Global Controller Advice中的处理程序方法与基于Controller的异常处理程序方法相同,并且在控制器类无法处理异常时使用。

  3. HandlerExceptionResolver - 对于通用例外,我们大多数情况下都会提供静态页面。 Spring Framework提供了HandlerExceptionResolver接口,我们可以实现它来创建全局异常处理程序。这种定义全局异常处理程序的额外方法背后的原因是Spring框架还提供了我们可以在spring bean配置文件中定义的默认实现类,以获得spring框架异常处理的好处。 SimpleMappingExceptionResolver是默认的实现类,它允许我们配置exceptionMappings,我们可以在其中指定用于特定异常的资源。我们还可以覆盖它以使用我们的应用程序特定更改创建我们自己的全局处理程序,例如记录异常消息。

答案 2 :(得分:1)

确保2件事情,您的代码将有效。

  1. 您的@ControllerAdvice课程在组件扫描路径中可用。
  2. 确保@ControllerAdvice中的方法的结构有点像这样 -
  3. @ExceptionHandler(value = { RequestProcessingException.class }) public @ResponseBody ResponseEntity<ErrorMessageBO> hotelConfigServiceExceptionHandler(HttpServletRequest request, RequestProcessingException e) { logger.error("Exception with tracking Id: {}, dev message: {} and Message:", RequestContextKeeper.getContext().getRequestId(), e.getDeveloperMessage(),e); return new ResponseEntity<ErrorMessageBO>(new ErrorMessageBO(e.getErrorCode(), e.getMessage(),RequestContextKeeper.getContext().getRequestId(),e.getDeveloperMessage()), HttpStatus.OK); }