文章目录
- 异常处理器
- 异常处理器快速入门
- 项目异常处理
异常处理器
异常处理器快速入门
程序开发过程中不可避免的会遇到异常现象
出现异常现象的常见位置与常见原因如下:
框架内部抛出的异常:因使用不规范导致
数据层抛出的异常:因外部服务器故障导致(例如:服务器访问超时)
业务层抛出的异常:因业务逻辑书写错误导致(例如:遍历业务书写操作,导致索引异常等)
表现层抛出的异常:因数据收集、校验等规则导致(例如:不匹配的数据类型间导致异常)
工具类抛出的异常:因工具类书写不严谨不够健壮导致(例如:必要释放的连接长期未释放等)
各个层级均出现异常,异常处理代码书写在哪一层都是不合适的
当出现异常, 我们让每一层的异常都不处理往上一层抛出, 所有的异常均抛出到表现层进行处理
表现层处理异常,如果每个方法中都单独书写try…catch…,代码书写量巨大且意义不强
采用AOP思想解决
SpringMVC提供了异常处理器:
集中的、统一的处理项目中出现的异常; 既然最终异常是在表现层进行统一处理, 那么我们异常处理器的类也需要写在表现层controller包下
@RestControllerAdvice类注解
定义在Rest风格开发的控制器增强类定义上方, 为Rest风格开发的控制器类做增强, 此注解自带@ResponseBody注解与@Component注解,具备对应的功能
@ExceptionHandler方法注解:
专用于异常处理的控制器方法上方, 用于设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行; 此类方法可以根据处理的异常不同,制作多个方法分别处理对应的异常
@RestControllerAdvice // 声明该类是用来做异常处理的
public class ProjectExceptionAdvice {
@ExceptionHandler(Exception.class) // 声明该方法是拦截所有异常
public Result doException(Exception ex) {
// 返回异常提示
return new Result(666, null, "出现异常");
}
}
项目异常处理
项目中的异常不能和上面的处理方式一样
项目异常分类:
业务异常(BusinessException)
- 规范的用户行为产生的异常
- 不规范的用户行为操作产生的异常
系统异常(SystemException)
- 项目运行过程中可预计且无法避免的异常, 例如服务器断电死机等
其他异常(Exception)
- 编程人员未预期到的异常
项目异常处理方案:
针对业务异常(BusinessException): 发送对应消息传递给用户,提醒规范操作
针对系统异常(SystemException):
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给运维人员,提醒维护
- 记录日志
针对其他异常(Exception):
- 发送固定消息传递给用户,安抚用户
- 发送特定消息给编程人员,提醒维护(纳入预期范围内)
- 记录日志
使用步骤:
- 创建一个exception包, 在该包下分别创建业务异常类和系统异常类:
创建业务异常类BusinessException继承自RuntimeException类
public class BusinessException extends RuntimeException {
// 添加一个编号用于识别异常
private Integer code;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public BusinessException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
创建系统异常SystemException继承自RuntimeException类
public class SystemException extends RuntimeException{
// 添加一个编号用于识别异常
private Integer code;
public SystemException(Integer code, String message) {
super(message);
this.code = code;
}
public SystemException(Integer code, String message, Throwable cause) {
super(message, cause);
this.code = code;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
}
- 自定义异常编码(持续补充)
public class Code {
public static final Integer SAVE_OK = 20011;
public static final Integer DELETE_OK = 20021;
public static final Integer UPDATE_OK = 20031;
public static final Integer SELECT_OK = 20041;
public static final Integer SAVE_ERR = 20010;
public static final Integer DELETE_ERR = 20020;
public static final Integer UPDATE_ERR = 20030;
public static final Integer SELECT_ERR = 20040;
public static final Integer SYSTEM_ERROR = 50001; // 系统异常
public static final Integer SYSTEM_TIMEOUT_ERROR = 50002; // 请求超时
public static final Integer SYSTEM_UNKNOW_ERROR = 59999; // 系统未知异常
public static final Integer BUSINESS_ERROR = 60001; // 业务异常
}
- 触发自定义异常: 将可能出现的转换为自定义异常
示例: 使用系统异常
@GetMapping("/{id}")
public Result selectById(@PathVariable Integer id) {
try {
int i = 1/0;
} catch (Exception e) {
throw new SystemException(Code.SYSTEM_TIMEOUT_ERROR, "服务器访问超时, 请稍后重试", e);
}
Book book = bookService.selectById(id);
boolean flag = book != null;
Integer code = flag ? Code.SELECT_OK: Code.SELECT_ERR;
String msg = flag ? "": "数据查询失败, 请重试!";
return new Result(code, book, msg);
}
示例: 使用业务异常
@GetMapping("/{id}")
public Result selectById(@PathVariable Integer id) {
if (id < 0) {
throw new BusinessException(Code.BUSINESS_ERROR, "请进行合法的操作");
}
Book book = bookService.selectById(id);
boolean flag = book != null;
Integer code = flag ? Code.SELECT_OK: Code.SELECT_ERR;
String msg = flag ? "": "数据查询失败, 请重试!";
return new Result(code, book, msg);
}
- 处理器拦截系统异常和业务异常并处理
@RestControllerAdvice // 声明该类是用来做异常处理的
public class ProjectExceptionAdvice {
@ExceptionHandler(SystemException.class) // 拦截系统异常
public Result doSystemException(SystemException e) {
// 记录日志...
// 发送消息给运维...
// 发送邮件给开发人员..
// 返回异常提示
return new Result(e.getCode(), null, e.getMessage());
}
@ExceptionHandler(BusinessException.class) // 拦截业务异常
public Result doBusinessException(BusinessException e) {
// 返回异常提示
return new Result(e.getCode(), null, e.getMessage());
}
@ExceptionHandler(Exception.class) // 其他异常: 拦截所有的异常
public Result doException(Exception ex) {
// 记录日志...
// 发送消息给运维...
// 发送邮件给开发人员..
// 返回异常提示
return new Result(Code.SYSTEM_UNKNOW_ERROR, null, "系统繁忙请稍后再试");
}
}