一、异常
- 可以通过预检查方式规避的RuntimeException异常不应该通过catch的方式来处理,比如:NullPointerException,IndexOutOfBoundsException等等。说明:无法通过预检查的异常除外,比如,在解析字符串形式的数字时,可能存在数字格式错误,不得不通过catch NumberFormatException来实现。
- 异常不能用作流程控制和条件控制。
- catch时请分清稳定代码和非稳定代码,对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。说明:对大段代码进行try-catch,使程序无法根据不同的异常做出正确的应激反应,也不利于定位问题。
- 捕获异常必须要处理,如果不想处理它,将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
- 有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回滚事务。
- finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。JDK7及以上,可以使用try-with-resources方式。不要在finally块中使用return。
- 捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。
- 在调用RPC、二方包、或动态生成类的相关方法时,捕捉异常必须使用Throwable类来进行拦截。通过反射机制来调用方法,如果找不到方法,抛出NoSuchMethodException。
- 方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回null值。
- NPE产生的场景:1)返回类型为基本数据类型,return包装数据类型的对象时,自动拆箱有可能产生NPE。2)数据库的查询结果可能为null。3)集合里的元素即使isNotEmpty,取出的数据元素也可能为null。4)远程调用返回对象时,一律要求进行空指针判断,防止NPE。5)对于Session中获取的数据,建议进行NPE检查,避免空指针。6)级联调用obj.getA().getB().getC();一连串调用,易产生NPE。使用JDK8的Optional类来防止NPE问题。
- 定义时区分unchecked / checked异常,避免直接抛出newRuntimeException(),更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常。推荐业界已定义过的自定义异常,如:DAOException / ServiceException等。
- 对于公司外的http/api开放接口必须使用“错误码”;而应用内部推荐异常抛出;跨应用间RPC调用优先考虑使用Result方式,封装isSuccess()方法、“错误码”、“错误简短信息”。说明:关于RPC方法返回方式使用Result方式的理由:1)使用抛异常返回方式,调用方如果没有捕获到就会产生运行时误。2)如果不加栈信息,只是new自定义异常,加入自己的理解的error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。
- 避免出现重复的代码,必要时抽取共性方法,或者抽象公共类,甚至是组件化。
二、日志
- 应用中不可直接使用日志系统(Log4j、Logback)中的API,而应依赖使用日志框架SLF4J中的API,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
- 所有日志文件至少保存15天。网络运行状态、安全相关信息、系统监测、管理后台操作、用户敏感操作需要留存相关的网络日志不少于6个月。
- 应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log。logType:日志类型,如stats/monitor/access等;logName:日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。说明:推荐对日志进行分类,如将错误日志和业务日志分开存放,便于开发人员查看,也便于通过日志对系统进行及时监控。
- 在日志输出时,字符串变量之间的拼接使用占位符的方式。
- 对于trace/debug/info级别的日志输出,必须进行日志级别的开关判断。
- 避免重复打印日志,浪费磁盘空间,务必在log4j.xml中设置additivity=false。
- 异常信息应该包括两类信息:案发现场信息和异常堆栈信息。如果不处理,那么通过关键字throws往上抛出。
- 生产环境禁止输出debug日志;有选择地输出info日志;如果使用warn来记录刚上线时的业务行为信息,一定要注意日志输出量的问题,避免把服务器磁盘撑爆,并记得及时删除这些观察日志。
- 可以使用warn日志级别来记录用户输入参数错误的情况,避免用户投诉时,无所适从。如非必要,请不要在此场景打出error级别,避免频繁报警。(error级别只记录系统逻辑出错、异常或者重要的错误信息。)