原创一个微型的日志工具类
JDK 自带的 java.util.logging 非常简陋,于是在此基础上新建 LogHelper 类,封装一些实用的功能。
完整源码在:https://gitee.com/sp42/ajaxjs-base/tree/master/src/main/com/ajaxjs/util/logger
- 封装了三种最常用的方法,分别是 config、info 和 warning 方法,均支持带有多个日志消息的对象参数,warning 支持传入 Throwable 异常的参数。
- 可以定位日志所发生的行数及类 java 源文件的超链接,大大便于调试;
- 通过 FileHandler 实现 WARNING 级别的或以上的日记磁盘记录,按照当前日期命名
一般情况下通过工厂模式创建 LogHelper,执行 LogHelper.getLog() 并传入目标类的 class 引用。
public class TestLogHelper {
// 创建类成员为日志服务
private static final LogHelper log = LogHelper.getLog(TestLogHelper.class);
public void testGetLog() {
// …… 其他代码
log.warning("发生异常!……");
log.info("bar");
log.warning("fooo");
// 带有多个日志消息的对象参数,用 {0},{1},{2} 预留消息位置
log.warning("脚本引擎 {0} 没有 {1}() 这个方法", "js", "foo");
log.warning(new Exception("致命错误!"), "脚本引擎 {0} 没有 {1}() 这个方法", "js", "foo");
}
.......
}
控制台现实结果如下所示。
LogHelper 更多方法的签名,参数 msg_tpl 为信息模版,用 {0},{1},{2} 预留消息位置
public void config(String msg);
public void config(String msg_tpl, Object... params);
public void info(String msg);
public void info(String msg_tpl, Object... params);
public void warning(String msg);
public void warning(String msg_tpl, Object... params);
public void warning(Throwable ex, String msg);
public void warning(Throwable ex, String msg_tpl, Object... params);
为什么 LogHelper 可以打印日志从哪个类的哪个方法来,知道是在哪一行代码上发生的?首先观察 API 原生调用 logger.logp(Level.WARNING, className, getMethodName(), msg),其中 className 是发出日志记录请求的类名,对此 LogHelper 已经把 className 作为属性保存起来了,直接传入即可;而 getMethodName() 是发出日志记录请求的方法名,这是个中的关键。下面是 getMethodName() 的源码。
public class LogHelper {
private String className; // 所在的类名
......
/**
* 获取所在的方法,调用时候
*
* @return 方法名称
*/
private String getMethodName() {
StackTraceElement ste = null;
// Thread.getCurrentThread().getStackTrace() 暴露了当前线程的运行栈信息
for (StackTraceElement _ste : Thread.currentThread().getStackTrace()) {
String clzName = _ste.getClassName();
if (_ste.isNativeMethod() || clzName.equals(Thread.class.getName()) || clzName.equals(getClass().getName()))
continue; // 过滤不要的类
if (clzName.equals(className)) {
ste = _ste;
break;
}
}
if(ste != null) {// 超链接,跳到源码所在行数
return String.format(".%s(%s:%s)", ste.getMethodName(), ste.getFileName(), ste.getLineNumber());
}else{
return null;
}
}
.....
}
Thread.getCurrentThread().getStackTrace() 返回当前线程的运行栈信息,结果是 StackTraceElement[] 数组。java.lang.StackTraceElement 专门用于跟踪堆栈元素的信息,通过其源码可见:
public final class StackTraceElement implements java.io.Serializable {
// Normally initialized by VM (public constructor added in 1.5)
private String declaringClass; // 类名
private String methodName; // 方法名
private String fileName; // 文件名
private int lineNumber; // 行号
……
}
这正好是为当前类名、方法名、文件名、行号等信息准备的。
最后,String.format(“.%s(%s:%s)”, …) 的格式是固定的,只要符合这种格式,控制台就可以输出类的超链接。
上一篇: 字符串排序问题
下一篇: C语言实现中英文混合字符串截取
推荐阅读
-
采用封装及反射原理封装一个将对象装换为对数据库操作的工具类
-
C#编写了一个基于Lucene.Net的搜索引擎查询通用工具类:SearchEngineUtil
-
一个很方便的 XML 类!!原创的噢_php基础
-
iOS实现封装一个获取通讯录的工具类详解
-
iOS实现封装一个获取通讯录的工具类详解
-
android上一个可追踪代码具体到函数某行的日志类
-
android上一个可追踪代码具体到函数某行的日志类
-
C#编写了一个基于Lucene.Net的搜索引擎查询通用工具类:SearchEngineUtil
-
.net工具类 分享一个简单的随机分红包的实现方式
-
java继承:定义交通工具类Vehicle,一个小车类Car,一个公共汽车Bus类,实现Car、Bus对Vehicle的继承