@ControllerAdvice覆盖异常@ResponseStatus

时间:2016-07-19 14:09:10

标签: spring spring-mvc spring-boot spring-annotations

我不确定原因,但@ControllerAdvice使用Exception注释覆盖@ResponseStatus级别定义的响应代码。

异常

@ResponseStatus(HttpStatus.BAD_REQUEST)
public class GreetException extends RuntimeException {}

控制器

@RestController
@RequestMapping("/")
public class GreetController {

    @RequestMapping(method = RequestMethod.GET)
    public String greet() {
        throw new GreetException();
    }
}

控制建议

@ControllerAdvice
public class ExceptionConfiguration {

    @ResponseStatus(HttpStatus.CONFLICT)
    @ExceptionHandler(RuntimeException.class)
    public void handleConflict() {}
}

当调用来自GreetController的greet方法时,响应为409 - CONFLICT。因为我特别提供了异常级别的响应代码,我预计这将是返回的代码(400 - BAD_REQUEST)。
当然,这是一个过于简化的示例,但我们定义了一个带有RuntimeException定义的控制器建议,因此我们可以为每个未捕获的异常分配一个id。

达到预期行为的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

使用@ResponseStatus注释异常的问题是,这只会在异常未在其他地方处理时触发。

请参阅Spring article about exception handling in Spring MVC

中的引用
  

当从控制器方法抛出带注释的异常,而不在其他地方处理时,它将自动导致使用指定的状态代码返回相应的HTTP响应。

尽管ControllerAdvice具有通用处理程序,但同一篇文章描述了使其工作的方法。请参阅Paragraph about ControllerAdvice

如果用@ResponseStatus注释,你基本上要做的就是在常规处理程序中重新抛出异常:

@ControllerAdvice
public class ExceptionConfiguration {

  @ResponseStatus(HttpStatus.CONFLICT)
  @ExceptionHandler(RuntimeException.class)
  public void handleConflict(RuntimeException e) throws RuntimeException {
    // Check for annotation
    if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
      // Rethrow Exception
      throw e;
    }
    else {
      // Provide your general exception handling here
    }
  }
}

答案 1 :(得分:1)

  

你的ControllerAdvice不知道GreetException,所以它是   抛出“HttpStatus.CONFLICT”而不是“HttpStatus.BAD_REQUEST”

请参阅以下弹簧文档:

https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc

请更改ControllerAdvice代码,如下所示:

@ControllerAdvice
public class ExceptionConfiguration {

    @ResponseStatus(HttpStatus.CONFLICT)
    @ExceptionHandler(RuntimeException.class)
    public void handleRuntimeException() {}

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(GreetException.class)
    public void handleGreetException() {}

}