这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
平时的API开发过程,我们总会在API的最外层加一个try...catch来捕获异常错误。这种方法简单粗暴,但是在每个API入口都去做这样的处理的话,代码不够优雅。所以我们要实现一个AOP来进行全局的异常处理。
@ControllerAdvice 和 @ExceptionHandler
@ControllerAdvice相当于controller的切面,主要用于@ExceptionHandler,@InitBinder和@ModelAttribute,使注解标注的方法对每一个controller都起作用。默认对所有controller都起作用,当然也可以通过@ControllerAdvice注解中的一些属性选定符合条件的controller
@ExceptionHandler用于异常处理的注解,可以通过value指定处理哪种类型的异常还可以与@ResponseStatus搭配使用,处理特定的http错误。标记的方法入参与返回值都有很大的灵活性
一、所有的API都需要相同的异常处理。
@ControllerAdvice
public class GeneralExceptionHandler {
@ExceptionHandler(Exception.class)
protected ResponseEntity<Error> handleException(Exception ex) {
MyError myError = MyError.builder()
.text(ex.getMessage())
.code(ex.getErrorCode()).build();
return new ResponseEntity(myError,HttpStatus.valueOf(ex.getErrorCode()));
}
}
二、有一个API,它需要一个或多个异常其他形式进行格式处理,与其他应用程序API不同。我们可以在 OtherController 内部添加 @ExceptionHandler 来处理 OtherException ,或者为 OtherController 创建新的@ControllerAdvice,以备我们也想在其他 API 中处理 OtherException。
@ControllerAdvice(assignableTypes = OtherController.class)
public class OtherExceptionHandler {
@ExceptionHandler(OtherException.class)
protected ResponseEntity<Error> handleException(OtherException ex) {
MyOtherError myOtherError = MyOtherError.builder()
.message(ex.getMessage())
.origin("Other API")
.code(ex.getErrorCode()).build();
return new ResponseEntity(myOtherError,HttpStatus.valueOf(ex.getErrorCode()));
}
}
三、我们有一个 API 需要以不同于应用程序中其他 API 的方式对异常进行格式化,但这次所有的异常都需要进行不同的转换。加上 @Order 注解的注意事项。因为现在我们需要告诉 Spring,在处理同一个异常时,哪个 @ControllerAdvice 的优先级更高。
@ControllerAdvice
public class GeneralExceptionHandler {
@ExceptionHandler(Exception.class)
protected ResponseEntity<Error> handleException(Exception ex) {
MyError myError = MyError.builder()
.text(ex.getMessage())
.code(ex.getErrorCode()).build();
return new ResponseEntity(myError, HttpStatus.valueOf(ex.getErrorCode()));
}
}
@ControllerAdvice(assignableTypes = OtherController.class)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class OtherExceptionHandler {
@ExceptionHandler(Exception.class)
protected ResponseEntity<Error> handleException(Exception ex) {
MyError myError = MyError.builder()
.message(ex.getMessage())
.origin("Other API")
.code(ex.getErrorCode()).build();
return new ResponseEntity(myError,HttpStatus.valueOf(ex.getErrorCode()));
}
}
如果是用的 @RestControllerAdvice 注解,它会将数据自动转换成JSON格式,不再需要 ResponseEntity 的处理来。这种与 Controller 和 RestController 类似,本质是一样的,所以我们在使用全局异常处理之后可以进行灵活的选择处理