Spring中自定义@ControllerAdvice用于异常处理

问题描述 投票:0回答:3

我正在尝试将休息控制器中的异常映射到具有主体的响应,并在中心位置执行此操作。

我试过这个:

@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 验证行为,并且我收到的响应不是我期望的 Error 对象。

我有什么遗漏的吗?

java spring rest exception controller-advice
3个回答
6
投票

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

就我而言,我使用像这样的controllerAdvice:

@ControllerAdvice
public class GlobalControllerExceptionHandler {

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

4
投票

Spring框架提供了以下方法来帮助我们实现健壮的异常处理。

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

  2. 全局异常处理程序 – 异常处理是一个横切关注点,应该对我们应用程序中的所有切入点进行处理。我们已经研究了 Spring AOP,这就是 Spring 提供 @ControllerAdvice 注释的原因,我们可以将其与任何类一起使用来定义全局异常处理程序。 Global Controller Advice 中的处理程序方法与基于控制器的异常处理程序方法相同,并在控制器类无法处理异常时使用。

  3. HandlerExceptionResolver – 对于通用异常,大多数时候我们提供静态页面。 Spring框架提供了HandlerExceptionResolver接口,我们可以实现它来创建全局异常处理程序。这种定义全局异常处理程序的额外方法背后的原因是 Spring 框架还提供了默认实现类,我们可以在 spring bean 配置文件中定义这些类,以获得 spring 框架异常处理的好处。 SimpleMappingExceptionResolver 是默认的实现类,它允许我们配置异常映射,在其中我们可以指定针对特定异常使用哪个资源。我们还可以重写它,以使用特定于应用程序的更改(例如记录异常消息)来创建我们自己的全局处理程序。


2
投票

确保满足两件事,您的代码就能正常工作。

  1. 您的
    @ControllerAdvice
    类在组件扫描路径中可用。
  2. 确保您的
    @ControllerAdvice
    中的方法具有类似这样的结构 -
    @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);
    }
© www.soinside.com 2019 - 2024. All rights reserved.