IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 《Mybatis源码》第20章 ErrorContext 全局异常信息 -> 正文阅读

[Java知识库]《Mybatis源码》第20章 ErrorContext 全局异常信息

# ErrorContext 错误日志

mybatis在读取mapper文件的时候,会存在下面这行代码,那么它用到了ErrorContext类,那么该类的作用是啥?

ErrorContext.instance().resource(resource);

MyBatis 还有一个很有意思的点在于异常日志的输出。不知道大家有没有发现,使用 MyBatis 时定位问题非常容易,我们只需要查看一下控制台的异常日志就能一目了然地知道问题出现在了哪里。就像这样:

https://upload-images.jianshu.io/upload_images/14707524-2db2f1284ed9fc46.png?imageMogr2/auto-orient/strip|imageView2/2/w/1195/format/webp

1.存储异常信息的字段

MyBatis 异常涵盖的信息总结为一点就是:异常是由谁在做什么的时候在哪个资源文件中发生的,执行的 SQL 是哪个,以及 java 详细的异常信息。这六个私有变量分别存储这些信息:

public class ErrorContext {  
  // 换行符,因为不同的系统,换行符可能不同,而该类的目的主要就是展示日志,
  private static final String LINE_SEPARATOR = System.getProperty("line.separator","\n");
  private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();

  private ErrorContext stored;
  // 异常文件
  private String resource;
  // 异常操作
  private String activity;
  // 异常对象
  private String object;
  // 异常信息
  private String message;
  // 异常sql
  private String sql;
  // 异常日志
  private Throwable cause;
  • resource:存储异常存在于哪个资源文件中。
    如:### The error may exist in mapper/AuthorMapper.xml
  • activity:存储异常是做什么操作时发生的。
    如:### The error occurred while setting parameters
  • object:存储哪个对象操作时发生异常。
    如:### The error may involve defaultParameterMap
  • message:存储异常的概览信息。
    如:### Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column ‘id2’ in ‘field list’
  • sql:存储发生日常的 SQL 语句。
    如:### SQL: select id2, name, sex, phone from author where name = ?
  • cause:存储详细的 Java 异常日志。
    如:### Cause: java.sql.SQLSyntaxErrorException: Unknown column ‘id2’ in ‘field list’ at

对于这六个成员变量的 “set” 方法,命名同相应成员变量,均是对成员变量做赋值操作并返回存储完相应信息后当前 ErrorContext 的实例。例如:

 public ErrorContext resource(String resource) {
    this.resource = resource;
    return this;
  }

  public ErrorContext activity(String activity) {
    this.activity = activity;
    return this;
  }

  // 其余省略...

2.使用 ThreadLocal 管理 ErrorContext

private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<ErrorContext>();

ThreadLocal 是本地线程存储,它的作用是为变量在每个线程中创建一个副本,每个线程内部都可以使用该副本,线程之间互不影响。使用 ThreadLocal 来管理 ErrorContext,保证了在多线程环境中,每个线程内部可以共用一份 ErrorContext,但多个线程持有的 ErrorContext 互不影响,保证了异常日志的正确输出。

ErrorContext采用了单例模式,保证了每个线程共用一份实例

  // 私有构造方法
  private ErrorContext() {
  }
  // 静态方法获取实例
  public static ErrorContext instance() {
    ErrorContext context = LOCAL.get();
    if (context == null) {
      context = new ErrorContext();
      LOCAL.set(context);
    }
    return context;
  } 

3.其它方法

stored 变量充当一个中介,在调用store()方法时将当前 ErrorContext保存下来,在调用 recall() 方法时将该 ErrorContext 实例传递给 LOCAL。

  public ErrorContext store() {
    stored = this;
    LOCAL.set(new ErrorContext());
    return LOCAL.get();
  }

  public ErrorContext recall() {
    if (stored != null) {
      LOCAL.set(stored);
      stored = null;
    }
    return LOCAL.get();
  }

reset()顾名思义就是重置方法

public ErrorContext reset() {
    resource = null;
    activity = null;
    object = null;
    message = null;
    sql = null;
    cause = null;
    LOCAL.remove();
    return this;
  }

toString()方法就是显示我们的错误信息

@Override
  public String toString() {
    StringBuilder description = new StringBuilder();

    // message
    if (this.message != null) {
      description.append(LINE_SEPARATOR);
      description.append("### ");
      description.append(this.message);
    }

    // resource
    if (resource != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error may exist in ");
      description.append(resource);
    }

    // object
    if (object != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error may involve ");
      description.append(object);
    }

    // activity
    if (activity != null) {
      description.append(LINE_SEPARATOR);
      description.append("### The error occurred while ");
      description.append(activity);
    }

    // activity
    if (sql != null) {
      description.append(LINE_SEPARATOR);
      description.append("### SQL: ");
      description.append(sql.replace('\n', ' ').replace('\r', ' ').replace('\t', ' ').trim());
    }

    // cause
    if (cause != null) {
      description.append(LINE_SEPARATOR);
      description.append("### Cause: ");
      description.append(cause.toString());
    }

    return description.toString();
  }

4.Mybatis使用

mybatis是如何使用的,其实这个就相当于是一个进度,例如上面的那行代码,就是把资源路径存入,然后在后面执行SQL的时候,会继续存入其它的信息

// 把加载的资源文件路径存入
ErrorContext.instance().resource(resource);

这里还有一个小细节,为啥这些赋值方法,要返回this当前这个对象,因为这样就更方便多个赋值,例如ErrorContext.instance().message(message).cause(e).toString(),这样赋值操作1行就可以搞定

5.ErrorContext

text.instance().resource(resource);


这里还有一个小细节,为啥这些赋值方法,要返回`this`当前这个对象,因为这样就更方便多个赋值,例如`ErrorContext.instance().message(message).cause(e).toString()`,这样赋值操作1行就可以搞定

## 5.ErrorContext

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-26 08:43:52  更:2021-11-26 08:46:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:45:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码