《码出高效》五 异常与日志

前言

本章主要是讲异常处理,关于异常主要有三个问题:
哪里发生异常
谁来处理异常
如何处理异常
围绕这三个问题就有了一套异常处理机制

异常分类

通常异常时针对不稳定代码的,并且需要区分类型

  • throw和throws的区别:
    《码出高效》五 异常与日志_第1张图片
    以此段代码为例,thrwo是方法内部具体抛出异常的关键字,thrwos则跟在方法签名,表示方法可以向上抛出异常
  • 异常被捕获后,如果没有必要对外透出且方法可以处理,就直接捕获并处理;否则向上抛出,由上层方法和框架处理
  • 异常捕获后,必须根据业务场景进行相应处理,例如重试,回滚等,打印日志和抛出也需要添加好参数,便于定位问题
  • JDK的异常机制中,Throwable是所有异常父类
  • 《码出高效》五 异常与日志_第2张图片
    如图,异常分为Error(致命异常)和Exception(非致命异常) ,Excepttion又可以分为checkde异常(受检异常)和unchecked异常(非受检异常),
  • Error一般是无法由程序处理,只能人工介入的,如StackOverflowError、
    OutofMemoryError
  • checked受检异常就是需要在代码里处理的异常,否则会编译错误,例如sqlexception,ClassnotFoundException,这类细分出的引起注意类就是没法处理的,例如sql异常重试也无用,只能保存现场,调试解决,可处置的比如unauthorized异常,就可以跳转到权限申请页面
  • unchecked异常,常见叫法是runtimeException,运行时异常,因为他们继承于这个接口,不需要程序进行显式捕捉和处理
  • 细分可分为三类:
  • 可预测异常Predicted Exception:例如IndexOutOtBoundsException 、NullPointerException 等,这种异常不应该产生,可以提前检查判断避免
  • 需捕捉异常( Caution Exception ),例如远程调用超时DubboTimeoutException,客户端需显式处理
  • 可透出异常
    Ignored Exception,此类框架或者系统会自行处理,程序无需关系

文章中有一个很好的例子,出国旅行
机场地震,不可抗力,属于error,做计划时不需要考虑这些异常
中途堵车,属于checked异常,可以提前出发或者改签,其中飞机延误需要check但无能为力
没有带护照,可以提前预料,是可预测异常
车子损坏,属于需要捕捉异常,必须处理
检票机器故障,可透出异常,无需乘客关心

try代码块

  • try-catch-finally三者中,try必不可少,另外两个至少存在一个
    try:监视代码执行过程,有异常则跳转到catch,没有catch,则跳转到finally
    catch:没有异常就不执行,有异常就处理或向上抛出
    finally:是否有异常都会执行,outofMemoryError也会执行
    没有执行可能有三种情况:
    · 没有进入try 代码块。
    · 进入try 代码块, 但是代码运行中出现了死循环或死锁状态。
    · 进入try 代码块, 但是执行了System. exit() 操作。
    《码出高效》五 异常与日志_第3张图片
    在这里插入图片描述
  • 如上,程序输出10001,说明finally是在return后执行的,return的结果会暂存,执行finally后输出暂存结果
  • 在finally中做操作非常危险,会使得结果不可控
  • try与锁的关系
    《码出高效》五 异常与日志_第4张图片
    这段代码中,可能出现lock方法报出的unchecked异常,之后执行finally对未加锁的对象解锁造成程序中断,加锁失败的原因就会被覆盖,那么把红色部分放到try的上方
  • 例如Lock 、ThreadLocal 、InputStream这些都需要在finally中进行显式清理,避免内存泄露

异常的抛与接

  • 异常处理中,被捕获的异常需要是被抛出异常的父类
  • 远程服务调用中推荐使用result对象封装异常信息,因为抛异常返回的话,可能出现调用方法没有捕获,出现运行时错误,进而程序中断;还有就是添加栈信息会造成很大传输消耗,不添加又不便定位错误
  • 为了防止空指针异常,需要方法返回值可以为null,当然需要注释返回null的情况

日志

日志就像航空领域的黑匣子,一般是记录操作轨迹,监控系统运行状况,回溯系统故障
日志规范:
推荐命名规范为appName_logType logName.log,logType即日志类型,logName即日志描述
日志的保存时间:推荐保存时间为15天,根据重要程度,文件大小,磁盘空间可自行延长时间
日志级别:
• DEBUG 级别曰志记录对调试程序有帮助的信息。
• INFO 级别日志用来记录程序运行现场,虽然此处并未发生错误,但是对排
查其他错误具有指导意义。
• WARN 级别日志也可以用来记录程序运行现场,但是更偏向于表明此处有出
现潜在错误的可能。
• ERROR 级别日志表明当前程序运行发生了错误,需要被关注。但是当前发
生的错误,没有影响系统的继续运行。
• FATAL 级别曰志表明当前程序运行出现了严重的错误事件,并且将会导致应
用程序中断。

  • 打印日志时需要注意的点
    1.预先判断日志级别
    《码出高效》五 异常与日志_第5张图片
    判断后再拼接,这样不会浪费系统资源,不需处理字符串
    2.避免无效日志打印
    生产环境禁止输出debug日志且有选择地输出info日志,使用info,warn级别时要控制日志输出量,节约磁盘,及时清理日志
    避免重复打印,务必在日志配置文件中设置additiv ity=false ,
    在这里插入图片描述
    3.区别对待错误日志
    warn,error都是与错误有关的日志,但不能笼统输出为error,因为这个就需要人为处理了
    除了系统逻辑错误,异常,或者违反业务规则,都可以归类为warn级别

4.保证记录内容完整
打印时需要注意两点
在这里插入图片描述

日志框架

《码出高效》五 异常与日志_第6张图片如上,是日志框架间的关系
1.日志门面
门面设计模式是面向对象设计模式的一种,它一般提供一套接口规范,自身不负责日志功能实现,使用者不需关注底层日志库,
2.日志库
开发者需要关注日志库的具体细节,比如logback或slf4j
3.日志适配器
日志门面适配器:slf4j规范是后提出的,之前的日志库没有实现这个接口,那么就需要适配器解决接口不兼容问题
日志库适配器:一些老项目里直接用api实现日志,之后要改为门面模式,就需要适配器完成迁移

  • 实际项目使用
    新工程推荐使用slf4j+logback
    《码出高效》五 异常与日志_第7张图片

老工程需要根据日志库确定门面适配器
《码出高效》五 异常与日志_第8张图片
《码出高效》五 异常与日志_第9张图片
如果用log4j的接口打印日志,还需要引入日志库适配器
《码出高效》五 异常与日志_第10张图片

之后再加入一个日志配置文件,logback.xml或者log4j.xml就可以打印日志
在这里插入代码片
private static final Logger logger= LoggerFactory.getLogger(Abc . class );这样定义可以避免new新对象,浪费内存资源

你可能感兴趣的:(java开发手册,java,数据库,sql)