wal*_*ros 5 java rest spring exception-handling spring-mvc
在Spring中,您可以通过@ControllerAdvice和@ExceptionHandler注释设置"全局"异常处理程序.我正在尝试利用这种机制来拥有两个全局异常处理程序:
RestControllerExceptionHandler - 对于任何带注释的控制器,它应该以json的形式返回错误响应 @RestControllerControllerExceptionHandler- 应该在屏幕上为任何其他控制器打印错误消息(附带有@Controller)问题是,当我声明这两个异常处理程序时,spring总是使用ControllerExceptionHandler和永远不会RestControllerExceptionHandler处理异常.
如何使这项工作?顺便说一句:我试图使用@Order注释,但这似乎不起作用.
这是我的异常处理程序:
// should handle all exception for classes annotated with
@ControllerAdvice(annotations = RestController.class)
public class RestControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
// below object should be serialized to json
ErrorResponse errorResponse = new ErrorResponse("asdasd");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
// should handle exceptions for all the other controllers
@ControllerAdvice(annotations = Controller.class)
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleUnexpectedException(Exception e) {
return new ResponseEntity<String>("Unexpected exception, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我删除ControllerExceptionHandler比RestControllerExceptionHandler春天正确调用时(仅适用于带注释的类@RestController)....但是当我添加时ControllerExceptionHandler,所有通过ControllerExceptionHandler.为什么?
经过深入调查后,字母顺序似乎很重要:/.
当我将我重命名RestControllerExceptionHandler为ARestControllerExceptionHandler(按字母顺序排在前面ControllerExceptionHandler)时,所有工作都按预期进行!ARestControllerExceptionHandler正确处理异常RestControllers并ControllerExceptionHandler处理来自其他控制器的异常.
我在春天为此创建了一个错误:https://jira.spring.io/browse/SPR-15432
---编辑:
我收到了SPR-15432的答案,建议可以使用@Order(org.springframework.core.annotation.Order)注释或通过实现Ordered接口来解决这种情况.
这对我来说不起作用,但似乎我导入了错误的@Order注释.(来自log4j2而不是spring).修好之后就行了.固定版本如下:
// should handle all exception for classes annotated with
@ControllerAdvice(annotations = RestController.class)
@Order(1) // NOTE: order 1 here
public class RestControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
// below object should be serialized to json
ErrorResponse errorResponse = new ErrorResponse("asdasd");
return new ResponseEntity<ErrorResponse>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
// should handle exceptions for all the other controllers
@ControllerAdvice(annotations = Controller.class)
@Order(2) // NOTE: order 2 here
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleUnexpectedException(Exception e) {
return new ResponseEntity<String>("Unexpected exception, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Run Code Online (Sandbox Code Playgroud)
这种情况正在发生,因为@RestController注释本身也是一个@Controller,因此Spring正在考虑使用@ControllerAdvice annotation = Controller.class.
你可以尝试另一种方法来定义@ControllerAdvice将有效的控制器子集,所以这里有一些解决方案:
创建一个新的注释@NotRestController:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotRestController {
}
Run Code Online (Sandbox Code Playgroud)使用@Controller和@NotRestController标记不是@RestController的控制器:
@Controller
@NotRestController
@RequestMapping("/controller")
public class SampleController {
}
Run Code Online (Sandbox Code Playgroud)使用NotRestController.class上ControllerExceptionHandler:
@ControllerAdvice(annotations = NotRestController.class)
public class ControllerExceptionHandler {
Run Code Online (Sandbox Code Playgroud)我Solution 1在Github上创建了一个示例项目并将其共享:
https://github.com/brunocleite/springexceptionhandlertest
将@RestController类移动到一个包中foo.bar,将@Controller类移动到另一个包中foo.nuk.
使用以下basePackages属性@ControllerAdvice代替annotations:
@ControllerAdvice(basePackages={"foo.bar"})
public class RestControllerExceptionHandler {
@ControllerAdvice(basePackages={"foo.nuk"})
public class ControllerExceptionHandler {
Run Code Online (Sandbox Code Playgroud)最好的祝福!