简体   繁体   English

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

[英]Custom @ControllerAdvice in Spring for exception handling

I am trying to map exceptions from my rest controllers to responses which have a body, and to do it in a central place. 我试图将我的其余控制器中的异常映射到具有主体的响应,并将其集中放置。

I have tried this: 我已经试过了:

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

The problem is that the handler is never triggered. 问题是处理程序永远不会触发。

If I define a custom method with @ExceptionHandler in my rest controllers, or extend something that has @ExceptionHandler , then all works well, but that introduces some bad design. 如果我在我的rest控制器中使用@ExceptionHandler定义一个自定义方法,或者扩展具有@ExceptionHandler东西,那么所有方法都可以正常工作,但这会带来一些不良设计。

It is my understanding that Spring will first try to look in controller for exception handling methods, then it will check for registered handlers. 据我了解,Spring首先会尝试在控制器中查找异常处理方法,然后将检查注册的处理程序。

I am trying to verify the behaviour via WebMvcTest, and responses I'm getting are not the Error objects that I'm expecting. 我正在尝试通过WebMvcTest验证行为,并且得到的响应不是我期望的Error对象。

Is there something I'm missing? 有什么我想念的吗?

The ControllerAdvice is a configuration that have to be registered by Spring. ControllerAdvice是必须由Spring注册的配置。 You have to move your class in the config package or you can register it by annotation. 您必须将类移到config包中,也可以通过注释进行注册。

In my case, I work with a controllerAdvice like this one : 就我而言,我使用的controllerAdvice像这样:

@ControllerAdvice
public class GlobalControllerExceptionHandler {

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

Spring Framework provides following ways to help us achieving robust exception handling. Spring Framework提供了以下方法来帮助我们实现可靠的异常处理。

  1. Controller Based – We can define exception handler methods in our controller classes. 基于控制器 –我们可以在控制器类中定义异常处理程序方法。 All we need is to annotate these methods with @ExceptionHandler annotation. 我们所需要做的就是用@ExceptionHandler注释对这些方法进行注释。 This annotation takes Exception class as argument. 该注释将Exception类作为参数。 So if we have defined one of these for Exception class, then all the exceptions thrown by our request handler method will have handled. 因此,如果我们为Exception类定义了其中一种,那么请求处理程序方法抛出的所有异常都将得到处理。 These exception handler methods are just like other request handler methods and we can build error response and respond with different error page. 这些异常处理程序方法与其他请求处理程序方法一样,我们可以构建错误响应并使用不同的错误页面进行响应。 We can also send JSON error response, that we will look later on in our example. 我们还可以发送JSON错误响应,我们将在示例后面查看。 If there are multiple exception handler methods defined, then handler method that is closest to the Exception class is used. 如果定义了多个异常处理程序方法,则使用最接近Exception类的处理程序方法。 For example, if we have two handler methods defined for IOException and Exception and our request handler method throws IOException, then handler method for IOException will get executed. 例如,如果我们为IOException和Exception定义了两个处理程序方法,并且我们的请求处理程序方法抛出IOException,则将执行IOException的处理程序方法。

  2. Global Exception Handler – Exception Handling is a cross-cutting concern, it should be done for all the pointcuts in our application. 全局异常处理程序 –异常处理是一个跨领域的问题,应该对我们应用程序中的所有切入点进行处理。 We have already looked into Spring AOP and that's why Spring provides @ControllerAdvice annotation that we can use with any class to define our global exception handler. 我们已经研究过Spring AOP,这就是Spring提供@ControllerAdvice批注的原因,我们可以将其与任何类一起使用来定义全局异常处理程序。 The handler methods in Global Controller Advice is same as Controller based exception handler methods and used when controller class is not able to handle the exception. Global Controller Advice中的处理程序方法与基于Controller的异常处理程序方法相同,并且在controller类无法处理异常时使用。

  3. HandlerExceptionResolver – For generic exceptions, most of the times we serve static pages. HandlerExceptionResolver –对于一般异常,大多数时候我们提供静态页面。 Spring Framework provides HandlerExceptionResolver interface that we can implement to create global exception handler. Spring框架提供了HandlerExceptionResolver接口,我们可以实现该接口来创建全局异常处理程序。 The reason behind this additional way to define global exception handler is that Spring framework also provides default implementation classes that we can define in our spring bean configuration file to get spring framework exception handling benefits. 这种定义全局异常处理程序的其他方法背后的原因是,Spring框架还提供了默认实现类,我们可以在我们的Spring bean配置文件中定义这些默认实现类以获得Spring框架异常处理的好处。 SimpleMappingExceptionResolver is the default implementation class, it allows us to configure exceptionMappings where we can specify which resource to use for a particular exception. SimpleMappingExceptionResolver是默认的实现类,它允许我们配置exceptionMappings,在其中可以指定用于特定异常的资源。 We can also override it to create our own global handler with our application specific changes, such as logging of exception messages. 我们还可以覆盖它,以使用应用程序特定的更改(例如,记录异常消息)来创建自己的全局处理程序。

Make sure of 2 things and your code will work. 确保两件事,您的代码将正常工作。

  1. Your @ControllerAdvice class is available in component-scan path. 您的@ControllerAdvice类在组件扫描路径中可用。
  2. Make sure the methods in your @ControllerAdvice have structure somewhat like this- 确保@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);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring 使用@ControllerAdvice 处理异常 - Spring Exception Handling using @ControllerAdvice Spring ControllerAdvice和身份验证/授权异常处理 - Spring ControllerAdvice and authentication/authorization exception handling ControllerAdvice 无法在 Spring 引导中捕获自定义异常 - ControllerAdvice cannot catch custom exception in Spring Boot @ControllerAdvice没有处理异常 - @ControllerAdvice is not handling exception ControllerAdvice不处理异常 - ControllerAdvice not handling exception Spring异常处理 - @ControllerAdvice无法处理HttpServletResponse#sendError() - Spring Exception Handling - @ControllerAdvice cannot handle HttpServletResponse#sendError() @ControllerAdvice异常处理与@ResponseStatus一起 - @ControllerAdvice exception handling together with @ResponseStatus Spring Boot @ControllerAdvice部分工作,不适用于自定义异常 - Spring Boot @ControllerAdvice partially working, not working for custom exception 即使我们在catch块中处理异常,如何使用@ControllerAdvice在Spring中处理异常 - How to handle exception in spring with @ControllerAdvice even though we are handling exception in catch block 使用@ControllerAdvice处理Spring Exception提供了集中控制,但是我们必须在方法签名中添加所有throws异常 - Spring Exception handling with @ControllerAdvice provides centralized control but we have to add all throws exception in method signature
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM