如何优雅的处理接口返回值异常? [学习核心包系列三]

项目的核心代码都封装在核心包中. 本系列文章记录笔者阅读源码的过程和相应的实践.

一个问题

当接口传入的数据检查无异常时, 程序将往数据库写数据, 如果写入异常. 当前接口没有做任何处理, 直接把错误返给调用方.

似乎, 这样不妥当的.

1
2
3
4
5
需求:

程序应该记录下数据库原始错误. 并返给调用方一个温柔的响应.

那么, 如何实现?

解决问题

  1. 首先在Dao层增加异常捕获, 看看能否打印出来.
1
2
3
4
5
try {
insert = insert(sql);
} catch (Exception e) {
throw new YxException(e.getMessage());
}
  1. 增加一个自定义异常. 在Dao层抛出该异常.
1
2
3
4
5
public class YxDBException extends YXException {
public YxDBException(String message) {
super(message);
}

  1. 利用 ControllerAdvice. 批量处理该异常.
1
2
3
4
5
6
7
8
9
10
11
@Slf4j
@ControllerAdvice
public class ExceptionController {

@ExceptionHandler(YxDBException.class)
@ResponseBody
public Result IncorrectCredentialsException(YxDBException e) {
log.error(e.getMessage(), e.getException());
return ResultGenerator.genFailMessage("数据库写入失败, 请检查数据合法性");
}

  1. 按目前的方式, 在每一个方法上都增加捕获异常就可以解决问题. 可以但没有必要.

  2. 如果代码结构合理. 那么执行SQL的方法都应该在DAO层. 那么通过AOP拦截该层即可.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Slf4j
@Component
@Aspect
public class DaoAspect {
/**
* 在要增强方法上环绕执行(前后都可以执行)
* 注解参数: execution(* com.yxkj.jk.yibao.dao.*.*(..))
* 表示此方法在 com.yxkj.jk.yibao.dao下的任何方法,方法包含任何参数,任何返回值 的方法上都能执行
* 第一个 * : 表示方法返回值为任意值都能执行此增强逻辑
* 第二个 .*.* : dao目录下的任何dao的方法都能执行此增强逻辑
* (..) : 表示方法里的参数为任意值 (无论参数多少,大小,类型)都可以执行此增强逻辑
* @param pjp
* @return
*/
@Around("execution(* com.yxkj.jk.yibao.dao.*.*(..))")
public Object aspectDaoExcpet(ProceedingJoinPoint pjp) {
Object obj;

try {
obj = pjp.proceed();
} catch (Throwable e) {
throw new YxDBException(e.getMessage());
}

return obj;
}
}