1.1 响应用户操作异常时,能友好的提示用户。
1.2 良好的异常信息展示,开发运维人员能快速定位问题。
1.3 响应外部调用异常时,应能明确指明是内部异常还是调用条件不满足导致。
2.1、异常分类
内部异常:
资源环境导致(系统环境异常、数据库连接超时、第三方服务响应超时)
第三方服务错误响应
第三方响应结果错误
外部传入参数非法
错误的编码逻辑
错误的配置
异常的业务数据(业务数据缺失)
业务异常:
用户操作错误
业务条件不满足
2.2、系统中正确捕获异常抛出。
方法入参进行合法性验证:
对系统外部提供的接口,必须要进行参数验证(必须)
系统内部对外层提供接口,需进行验证
工具类进行参数验证
public 方法要进行验证
private 方法(不建议参数验证)
第三方响应结果合法性验证。
获取第三方法结果后,根据你们的约定进行验证。
业务处理前,对业务业务前置条件进行验证。
业务处理前,验证业务条件(验证佘额、验证这个帐户有没有被公安门锁定)
要考虑性能成本(验证身份证号码是不是存在的)
业务处理后,对处理结果进行验证。如:验证对方帐户是不是到帐了,转出帐户是不是成功扣款
对于可能会出现异常的代码进行 try catch 捕获。
尝试恢复处理
直接抛出
转换后抛出
2.3、在系统出口统一拦截处理。
统一拦截的目的是确保出去的异常是可控的,调用方能够明白的异常信息。
这里出口是指系统对外统一响应逻辑,一般我们可分三类场景:
WEB Response
内部异常:引导至异常提示页。
业务异常:返回对应提示消息至前端。
未知异常:尝试进行认别,如果认识不了,转换成 编码异常(BUG)。
Http API 接口响应
内部异常:返回接口不可用消息。
参数错误:基于API文档中的异常列表进行进行响应返回。表明参数非法,需要调用方加强参数合法性验证
业务错误:基于掊口约定反回对应code与消息。
RPC Service 响应
内部异常:返回服务不可用消息
参数错误:基于接口文档进行响应,直接返回异常堆栈。
业务错误 :直接返回异常堆栈。
checkedException 与uncheckedException 声明原则
如果是参数非法抛出,返回结果非法(即软件BUG) uncheckedException
如果你认为调用方程序员需要有意识地采取措施,那么抛出检查型异常。
程序产品有明确的条件约束的要求,可声明检测型业务异常
3.1 异常的定义技巧
基于分包表示异常的分类,不建议使用继承
如果继承并不能直观的知道此异常为什么类型
业务异常可以新建包serviceexception
系统异常可以新建包systemexception
创建异常来类定义业务异常,不建议使用Code来定义
建议使用枚举类型
使用枚举来表示业务异常的几种结果,不建议使用code
3.2 统一对异常进行分类处理
异常转换
异常信息处理
逻辑断言
参数合法性验证
返回结果合法性验证
3.3 异常捕获
3.31 统一对异常进行拦截处理
目的:防止不明确的异常流出系统
RPC Service 响应拦截
Web Control 响应拦截
Http API 响应拦截
4.常见错误异常处理方式
直接勿略异常(不推荐):
try {
new String(source.getBytes("UTF-8"), "GBK");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
正确的处理(推荐):
try {
new String(source.getBytes("UTF-8"), "GBK");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("环境不支持UTF-8",e)
}
业务异不提供任何信息
public class DuplicateUsernameException extends Exception {
}
给每个异常处理都定义一个Code
用一个统一异常替代所有业务异常(不推荐)
public class ServiceException extends RuntimeException {
public ServiceException(Exception e) {
super(e);
}
public ServiceException(String message) {
super(message);
}
}
错误:
1、必须明确定义业务异常
2、尽可能申明成checkedException
3、要带上具体的业务数
正确方式:
定义明确的业务异常
常见错误码设计方案:统一格式:A-BB-CCC
A:错误级别,如1代表系统级错误,2代表服务级错误;
B:项目或模块名称,一般公司不会超过99个项目;
C:具体错误编号,自增即可,一个项目999种错误应该够用;
错误码暂定都是5位数字,并配有相应的英文解释
错误码为 0 表示成功,其他都表示错误
错误码按模块按功能场景分级分段,前三位错误码表示模块,第四位表示模块下的功能。
举例:商城系统里有交易模块和商品模块,则可以这样划分:
401开头的表示交易模块;
402开头的表示商品模块;
4011开头的表示交易模块里的下单场景需要用到的错误码,
4021表示商品模块下的添加商品场景里需要用到的错误码。
【说明】如果某个场景功能下需要的比较多的错误码,则可以使用其他未被使用的码段,即该场景功能可以拥有多个码段,然后通过添加注释等方式让人理解即可。
数字 1 开头的错误码表示系统级别的错误.
比如缺少某种字符集,连不上数据库之类的,系统级的错误码不需要分模块,可以按照自增方式进行添加
数字 4 开头的错误码表示API参数校验失败.
比如 “交易模块下单场景中,订单金额参数不能为空” 可以用 40111 错误码来表示
数字 5 开头的错误码表示后台业务校验失败.
比如 “交易模块下单场景中,该用户没有下单权限” 可以用 50111 错误码来表示
数字 4 开头的错误码与数字 5 开头的错误码对应的模块分类需要保持一致,即 4011 表示交易模块下单场景的API错误,5011 表示交易模块下单场景的业务错误.
错误码按需分配,逐步增加,灵活扩展.
淘宝开放平台公共返回码说明[https://developer.alibaba.com/docs/doc.htm?articleId=112813&docType=1]
Error code - 微博API
百度Open API错误码定义
公共错误码| 微信开放文档 [https://developers.weixin.qq.com/doc/oplatform/Return_codes/Return_code_descriptions_new.html]