异常捕获:
try:
可能产生异常的代码。try代码块某条语句产生异常,跳到catch语句块,try中未执行完的语句直接跳过。
catch:
发生异常并且被捕获,才执行catch中代码块。没有产生异常或异常不匹配导致捕获失败,跳过相关catch代码快。
异常捕获失败,没有catch语句块捕获成功,执行完finally语句块,异常继续向上抛出。
try代码块可能会引发多种类型的异常,引发异常时,按顺序来查看每个 catch 代码块,执行第一个与异常类型匹配的catch块,其后catch块将忽略。
异常捕获原则:catch应优先捕获最特殊的异常,然后逐渐一般化。即先子类后父类。避免产生编译时异常:Unreachable/has already been caught。
finally:
无论是否发生异常,代码必定执行。除非执行了System.exit(1),程序退出java虚拟机。
try-catch中有return语句,先执行finally,再执行return;
throw:
主动抛出一个异常。
异常分类:
Throwable:
Erro:程序不可预料的错误。程序无法处理。
Exception:可捕获处理。检查时异常,运行时异常。
检查时异常:
除了RuntimeException及其子类的所有异常。包括RuntimeException的父类Exception自身也是检查时异常。
编译期就暴漏的异常,一定要try-catch捕获处理或者throws向上抛出。
运行时异常:
运行时异常在编译器不会报错,可以不用手动处理。个人建议少用运行时异常,能捕获的尽量捕获,不要一直抛出。
异常处理原则:
a()-调用->b()-调用-c()。
本地捕获处理还是向上抛出?
本地处理:
a方法调用b方法,a方法无需知道b方法是否成功或者错误,则b方法自己处理异常,不要向上抛出。
向上抛出:
a方法调用b方法,a方法需要知道b是否成功或者失败,则b方法不能自己处理掉异常,应该向上抛出。如被@Transaction修饰的a方法。
异常和业务开发:
单条单据:
保证单挑单据的业务处理一定不会有异常抛出。
/**
* 保证该函数一定不会向上抛出异常
* @return
*/
public ResponseDTO tryHandle(参数列表){
ResponseDTO responseDTO = null;
try {
responseDTO = singleBill(参数列表);
}catch(E e){
StringBuilder logInfo = new StringBuilder("接口报错-接口名称-报错领域:")
.append("\r\n错误信息:")
.append(e.toString())
.append("\r\n请求参数:")
.append("领域入口参数");
log.info(logInfo.toString());
// 构建失败响应:至少包括,失败响应标识,失败响应信息
responseDTO = new ResponseDTO();
}
return responseDTO;
}
/**
* 单条单据逻辑函数
* @return
*/
public SingleResponseDTO singleBill(参数列表){
// 业务逻辑代码
// 关键地方记录日志
// 日志记录
log.info("请求第三方平台或者其他微服务前:请求参数");
请求第三方平台或者其他微服务
log.info("请求第三方平台或者其他微服务:响应单数");
if(业务判断,业务失败){
// 主动抛出异常,包括运行时异常和检查时异常。
// 异常应包含关键信息,用于户客户提示或错误查询
// 抛出异常的情况:
//1:结果为null,或结果中必要的字段或集合为空(null或者size=0)
throw new 异常类(基础异常信息,当前单据关键信息,如请求+响应参数);
}
正常业务步骤。。。
return sucessResponse;
}
异常捕获-批量单据:
/**
* 批量单据操作
* @return
*/
public BatchResponseDTO batchBill(参数列表){
// 循环请求单个单据处理函数,然后根据成功失败分组。
// 保证单个单据处理函数,一定不会抛出异常,自行处理了。
Map<Boolean,List<SingleBillResponseDTO>> responseMap = stream
.map(e->tryHandle(e))
.collect(Collectors.groupingBy(function<singleBill,boolean>));
StringBuilder logInfo = new StringBuilder("接口名称-领域名称-操作结果:\r\n成功数量:")
.append(responseMap.get(true).size())
.append("\r\n失败数量:")
.append(responseMap.get(false).size())
.append("\r\n失败信息:\r\n");
responseMap.get(false).stream().forEach(e -> logInfo.append(e.toString()));
tool.info(logInfo.toString());
// 构建批量响应参数,或者更新数据库等业务逻辑
BatchResponseDTO batchResponseDTO = new BatchResponseDTO(responseMap);
return batchResponseDTO;
}