5.【Java开发手册】| 异常日志

这里我就列出一些我认为应当遵守的,并且添加一些我自己在工作中的一些感受,如果照着文档抄,那完全变成练习打字了,浪费读者时间,如果你也认同我的看法,或者和我有类似感受,可以点个关注,共同进步,如果有不同意见,欢迎指出。

一、错误码

这个我就不列举阿里的规范要求了,因为大家都有自己的一套规则,这是阿里的定义方式,我觉得没有必要完全模仿。

首先错误码的作用就是,让我们能够快速定位到错误所在位置,并且在定义异常时能够有一个统一的标准。

错误码在设计指定规则的时候应当考虑支持不断追加的方式,以适应项目不断迭代带来的问题。

基于目前基本都是前后端分离的模式,基于 RESTful 风格,后端都是统一返回一个JSON格式的响应,而这个返回对象,通常包含,code,data, message 这些字段。

如果一切正常,也要返回一个错误码,阿里规定 00000,这个可以按照自己随便定义,我们规定的是20000,对应 Http 响应码 200

先介绍一下阿里的错误码制定规则:

  1. 使用字符串类型,共 5 位。错误来源 + 四位数字编码
  2. 错误来源分 用户/当前系统/第三方服务,分别对应 A/B/C
  3. 数字编码从 0001 到 9999,大类之间步长预留 100
  4. 错误码又分为三级,
    1. 每个来源的第一号,被定义为一级宏观错误码,比如 A0001/B0001/C0001
    2. 每个系统或者说模块中的开始被定义为二级宏观错误码,比如 A0100/A0200/B0300/C0400 (由步长决定)
    3. 具体在范围间的被定义为三级错误码,比如:A0101/B0102/C0103 这些。
    4. 00000 表示一切正常
  5. 错误码由统一平台管理,申请,审批生效。
  6. 避免随意定义新的错误码,尽可能在已经定义的错误码中找到语义相近的使用即可

我们可以参考阿里这套规则制定我们自己的一套规则,我之前会有疑惑步长100会不会不够用,后来想想,连阿里都够用了,我们这小公司还能超了不成,纯属多虑了。

二、异常处理

  1. 不要去捕获一下可以通过预检规避的 RuntimeException,比如一些查询结果可能为 null 的情况。
  2. 异常本来设计的初衷是解决一些意外情况,不要把他当作一种判断手段,我之前就碰到过这么写代码的同事,大概逻辑是,正常情况执行A流程,如果有异常则走B流程,这样做违背了异常设计的初衷,而且效率也比条件判断低很多。
  3. 捕获异常必要要处理它,不要捕获了什么都不做,这个我在 CodeReview 的时候就发现过,有的为了程序不抛出异常,手动 try 捕获,但是不做任何处理,这样有严重的安全隐患,隐藏了代码执行真实情况,如果不想处理可以抛出给上一层调用者。
  4. 在事务场景中,如果手动 catch 要注意可能会导致事务无法回滚。
  5. finally 块对资源对象或者流对象关闭的时候,有异常也要 try-catch
  6. finally 中不要写 return,否则会导致 try 块中的 return 失效。
  7. 捕获异常与抛出的异常要相匹配,或者捕获的是抛出异常的父类
  8. 一些注意NPE的场景
    1. 返回类型是基本类型,但是 return 的时候给的是包装类型,自动拆箱的时候可能产生 NPE
    2. 数据库查询结果可能是 null
    3. 集合里的元素即使是 isNotEmpty,取出的数据也可能是 null
    4. 远程调用返回对象时,一路要进行非空判断
    5. 对于 Sesson 中获取的数据,建议进行 NPE 判断
    6. 级联调用的时候,obj.getA().getB().getC(),易产生NPE
  9. 对于抛出去的异常使用具有业务含义的自定义异常

三、日志规约

  1. 使用 SLF4J,有利于维护和各个类的日志处理方式统一
  2. 日志文件至少保存 15 天,当天日志以 “应用名.log” 来保存,保存在/{统一目录}/{应用名}/logs/目录下,历史日志格式:{logname}.log.{保存日期},日期格式 yyy-MM-dd
  3. 根据国家法律,网络运行状态、网络安全事件、个人敏感信息操作等相关记录,留存的日志不少于六个月,并且进行网络多机备份。
  4. 应用中的扩展日志(如打点、临时监控、访问日志等)命名方式:appName_logType_logName.log。logType:日志类型,如stats/monitor/access等;logName:日志描述。这种命名的好处:通过文件名就可知道日志文件属于什么应用,什么类型,什么目的,也有利于归类查找。
  5. 在日志输出时,字符串变量之间的拼接使用占位符的方式。

说明:因为String字符串的拼接会使用StringBuilder的append()方式,有一定的性能损耗。使用占位符仅是替换动作,可以有效提升性能。正例:logger.debug(“Processing trade with id:{} and symbol:{}”,id,symbol);

  1. 对于trace/debug/info级别的日志输出,必须进行日志级别的开关判断:
  2. 避免重复打印日志,浪费磁盘空间,务必在日志配置文件中设置 additivity=false
  3. 日志打印时禁止直接用JSON工具将对象转换成String,使用对象的 toString 方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曹申阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值