这里使用的是java.util.logging: Logger
1.首先获得一个Logger对象
Logger myLogger = Logger.getLogger("com.mycompany.myapp");
2.设置Logger的记录等级
logger.setLevel(Level.FINE);
logger有7个可见等级,分别为
SEVERE
WARNING
INFO
CONFIG
FINE
FINER
FINEST
倘若不显式地添加上述语句,默认的可见等级是前三个。
3.再为Logger对象添加handler。
log.addHandler(handler);
handler相当于是对Logger的记录方式。
常用的有ConsoleHandler, FileHandler和SocketHandler.
在本学期的实验中,只使用了前两种。值得注意的是,FileHandler需要需要抛出异常,同时需要手动关闭(try(){}catch的机制不提供这里的自动关闭,且关闭时要先判断它是否为空)下面是一个例子:
还有一个现象,在多线程并发时,ConsoleHandler会使在添加log时会同时输出多条重复的log,且重复数目恰为当前的线程总数。可见在多线程工作中,不能随意调用ConsoleHandler;而FileHandler也要使每个线程的文件名不同才好(但是输出时,也还是很混乱,是所有线程中的Log混合着一块输出的)。
4.设置handler等级。同样地handler也有以上7个等级。
handler.setLevel(Level.FINEST);
注意:当Logger等级高于handler时,被记录下来的信息以logger与handler中的较高的为标准。
5.添加相应等级的记录
log.severe(“severe level”);
log.warning(“warning level”);
log.info(“info level”);
log.config(“config level”);
log.fine(“fine level”);
log.finer(“finer level”);
log.finest(“finest level”);
6.下面是一个简单的应用例子:
FileHandler handler = new FileHandler(“c:/log/20180418.log”);
logger.addHandler(handler);
handler.setLevel(Level.FINEST);
logger.addHandler(handler);
log.severe("severe level");
log.warning("warning level");
log.info("info level");
log.config("config level");
7.日志的规范化显示
为handler添加一个格式化器,同时重写其中的String format(LogRecord record) 方法:
handler.setFormatter(new Formatter() {
@Override
public String format(LogRecord record) {
return record.getLevel() + ":\t" + record.getMessage() + '\n';
}
});
8.日志信息的过滤,这里有一点不方便的就是,添加过滤条件之后,就不能查看完整的未经筛选的日志记录了。
handler.setFilter(filter);
这里的filter过滤器可以根据自己需要new一个,并重写过滤条件
1)按日志记录的时间段过滤
public Filter getFilterByTime() {
long d1 = 0, d2 = 0;
Pattern pat = Pattern
.compile("[0-9]{4}\\.[0-9]{2}.[0-9]{2}-[0-9]{2}:[0-9]{2}:[0-9]{2}\\s*");
try {
while (Math.abs(d1) < 1e-5 && Math.abs(d2) < 1e-5) {
DateFormat df = new SimpleDateFormat("yyyy.MM.dd-HH:mm:ss");
System.out.println("请输入起始时间(yyyy.MM.dd-HH:mm:ss):");
String time1 = in.nextLine();
System.out.println("请输入结束时间(yyyy.MM.dd-HH:mm:ss):");
String time2 = in.nextLine();
Matcher mat1 = pat.matcher(time1);
Matcher mat2 = pat.matcher(time2);
if (mat1.matches() && mat2.matches()) {
d1 = df.parse(time1).getTime();
d2 = df.parse(time2).getTime();
}
}
} catch (ParseException e) {
// TODO: handle exception
e.printStackTrace();
}
final long begin = d1, end = d2;
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
long t = record.getMillis();
return (t > begin && t < end) ? true : false;
}
};
}
2)按Log类型过滤
public Filter getFilterByLogType() {
String cho = null;
System.out.println("请输入要查询的Log类型(INFO或SEVERE)");
cho = in.nextLine();
switch (cho) {
case "INFO":
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
return (record.getLevel() == Level.INFO) ? true : false;
}
};
case "SEVERE":
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
return (record.getLevel() == Level.SEVERE) ? true : false;
}
};
default:
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
return true;
}
};
}
}
3)按log被记录时所在的类进行过滤
public Filter getFilterByClass() {
String cho = null;
System.out.println("请输入要查询的类:");
cho = in.nextLine();
final String className = cho;
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
//System.out.println(record.getSourceClassName());
return record.getSourceClassName().equals(className)?true:false;
}
};
}
4)按方法名进行过滤
public Filter getFilterByMethod() {
String cho = null;
System.out.println("请输入要查询的方法名:");
cho = in.nextLine();
final String methodName = cho;
return new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
return record.getSourceMethodName().equals(methodName)?true:false;
}
};
}
5)不过滤
Filter filter = new Filter() {
@Override
public boolean isLoggable(LogRecord record) {
// TODO Auto-generated method stub
return true;
}
};
当然,可以不用写得那么复杂,根据跟人需要进行重写.