@ControllerAdvice 覆盖异常@ResponseStatus
@ControllerAdvice overrides exception @ResponseStatus
我不确定为什么 @ControllerAdvice
使用 @ResponseStatus
注释覆盖了在 Exception
级别定义的响应代码。
异常:
@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。
实现预期行为的正确方法是什么?
用 @ResponseStatus
注释异常的问题是,这仅在异常未在其他地方处理时触发。
请参阅 Spring article about exception handling in Spring MVC 中的这句话:
When an annotated exception is thrown from a controller method, and not handled elsewhere, it will automatically cause the appropriate HTTP response to be returned with the specified status-code.
同一篇文章描述了在 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
}
}
}
Your ControllerAdvice does not know about GreetException, so it is
throwing "HttpStatus.CONFLICT" instead of "HttpStatus.BAD_REQUEST"
请查找以下 spring 文档供您参考:
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() {}
}
我不确定为什么 @ControllerAdvice
使用 @ResponseStatus
注释覆盖了在 Exception
级别定义的响应代码。
异常:
@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。
实现预期行为的正确方法是什么?
用 @ResponseStatus
注释异常的问题是,这仅在异常未在其他地方处理时触发。
请参阅 Spring article about exception handling in Spring MVC 中的这句话:
When an annotated exception is thrown from a controller method, and not handled elsewhere, it will automatically cause the appropriate HTTP response to be returned with the specified status-code.
同一篇文章描述了在 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
}
}
}
Your ControllerAdvice does not know about GreetException, so it is throwing "HttpStatus.CONFLICT" instead of "HttpStatus.BAD_REQUEST"
请查找以下 spring 文档供您参考:
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() {}
}