介绍
在一个复杂而又庞大的项目中分开处理可能出现的异常显然不现实,SpringBoot就为我们提供了一套优雅的解决方案--全局异常处理器。借助全局异常处理器可以统一处理项目运行时可能出现的异常
实现
/**
* 全局异常处理器,处理项目中抛出的业务异常
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 捕获业务异常
* @param ex
* @return
*/
@ExceptionHandler
public Result exceptionHandler(Exception ex){
log.error("异常信息:{}", ex.getMessage());
return Result.error(ex.getMessage());
}
}
解读
注解:
- @RestControllerAdvice:Spring MVC的全局异常处理注解,会自动捕获所有Controller层抛出的异常。
- @ExceptionHandler:当 Controller 层抛出异常时,Spring 会自动寻找带有该注解的方法来处理。
- @Slf4j:Lombok提供的日志注解,用于记录异常信息。
综上,异常被捕获到后会寻找带有@ExceptionHandler注解,且形参中的异常是该异常或其父类的方法,并进入方法体乖乖地等待你的处理~
实践
来看下面的方法如何实现处理数据库违反唯一约束(字段重复)的异常,并友好地返回异常提示。
/**
* 捕获SQL异常
* @param ex
* @return
*/
@ExceptionHandler
public Result exceptionHandler(SQLIntegrityConstraintViolationException ex){
String message = ex.getMessage();
if (message.contains("Duplicate entry")) {
String[] split = message.split(" ");
String username = split[2];
String msg = username + "已存在";
return Result.error(msg);
} else {
return Result.error(MessageConstant.UNKNOWN_ERROR);
}
}
- 拿到完整报错信息message,形如Duplicate entry 'value' for key 'key_name'。
- 二次确认异常类型,如果message中包含了Duplicate entry,那确实是我们期望处理的异常。
- 处理原始信息,拿到违反了唯一约束的值,并得到最终返回的msg。
- 给前端返回错误信息,例如在输入用户名时弹出”张三已存在“。
注意!
Spring按异常类型的继承关系匹配最具体的处理器,但如果方法参数过于宽泛(如Exception),可能拦截了本该由更具体方法处理的异常。
因此,建议处理异常方法的形参越具体越好