在日常的开发过程中,往往使用Log4J2、Logback日志框架,因为它们的性能比java提供的日志框架要好。也正是因为这样,导致对java的标准日志框架不是很了解。
日志级别&日志记录器
日志级别表示要在日志记录器中记录的级别(所有的日志都是记录在日志记录器中的,可以通过Logger.getLogger()函数获取一个日志记录器),从高到低依次为
- SEVERE:严重
- WARNING:警告
- INFO:信息
- CONFIG:配置
- FINE:精细
- FINER:精细
- FINEST:最精细
默认情况下日志记录器只会记录前3个级别的日志,即SEVERE、WARNING、INFO
举个例子:
public class LogTest {
/**
* 获取一个日志记录器,如果没有就会创建一个对应名称的日志记录器。
* 当前的日志记录器名为 'demo.LogTest'
*/
private static final Logger log = Logger.getLogger("demo.LogTest");
public static void main(String[] args) {
log.severe("hello,severe");
log.warning("hello,warning");
log.info("hello,info");
log.config("hello,config");
}
}
运行结果:
5月 08, 2023 9:00:13 下午 day4.demo4.LogTest main
严重: hello,severe
5月 08, 2023 9:00:13 下午 day4.demo4.LogTest main
警告: hello,warning
5月 08, 2023 9:00:13 下午 day4.demo4.LogTest main
信息: hello,info
private static final Logger log = Logger.getLogger("demo.LogTest");
会获取一个指定记录器名称的日志记录器,如果没有则会创建指定名称的日志记录器。最后一行日志没有记录和输出,因为前面说过默认只记录info及以上的级别。
日志处理器
日志记录器的作用是记录日志信息的,而日志处理器则是负责接收日志记录器的记录并将其输出到对应流。并且如果想要修改默认配置,将日志级别修改为CONFIG级别,就必须同时修改日志记录器和日志处理器的级别。
示例代码:
public class LogTest {
/**
* 获取一个日志记录器,如果没有就会创建一个对应名称的日志记录器。
* 当前的日志记录器名为 'demo.LogTest'
*/
private static Logger log = Logger.getLogger("demo.LogTest");
public static void main(String[] args) {
log.setLevel(Level.CONFIG);
//为日志记录器指定一个日志处理器
var handler = new ConsoleHandler();
handler.setLevel(Level.CONFIG);
log.addHandler(handler);
log.severe("hello,severe");
log.warning("hello,warning");
log.info("hello,info");
log.config("hello,config");
}
}
运行结果:
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
严重: hello,severe
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
严重: hello,severe
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
警告: hello,warning
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
警告: hello,warning
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
信息: hello,info
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
信息: hello,info
5月 08, 2023 9:30:40 下午 day4.demo4.LogTest main
配置: hello,config
可以看到CONFIG级别的日志信息也被打印出来了。但是现在输出的信息好像不太对,为什么会有重复的日志记录呢?这是由于日志记录器会将记录发送到自己的日志处理器和它父类日志记录器的日志处理器。所以需要做一个简单的设置
添加log.setUseParentHandlers(false);
语句,设置不使用父日志记录器的处理器
public class LogTest {
/**
* 获取一个日志记录器,如果没有就会创建一个对应名称的日志记录器。
* 当前的日志记录器名为 'demo.LogTest'
*/
private static Logger log = Logger.getLogger("demo.LogTest");
public static void main(String[] args) {
log.setLevel(Level.CONFIG);
//设置不使用父日志记录器的处理器
log.setUseParentHandlers(false);
//为日志记录器指定一个日志处理器
var handler = new ConsoleHandler();
handler.setLevel(Level.CONFIG);
log.addHandler(handler);
log.severe("hello,severe");
log.warning("hello,warning");
log.info("hello,info");
log.config("hello,config");
}
}
运行结果:
5月 08, 2023 9:35:17 下午 day4.demo4.LogTest main
严重: hello,severe
5月 08, 2023 9:35:17 下午 day4.demo4.LogTest main
警告: hello,warning
5月 08, 2023 9:35:17 下午 day4.demo4.LogTest main
信息: hello,info
5月 08, 2023 9:35:17 下午 day4.demo4.LogTest main
配置: hello,config
问题解决。
格式化器
Java日志框架中为日志记录器提供了多种种类的日志处理器,上面的示例中是ConsoleHanlder
,它会将日志信息输出到控制台。还有一种FileHandler
处理器,会将日志记录输出到文件中。
代码示例:
public static void main(String[] args) throws IOException {
log.setLevel(Level.CONFIG);
//设置不使用父日志记录器的处理器
log.setUseParentHandlers(false);
//为日志记录器指定一个日志处理器
var handler = new FileHandler("/Users/c/Desktop/file%u.log");
handler.setLevel(Level.CONFIG);
//默认为xml格式输出,这里修改为不用xml
handler.setFormatter(new SimpleFormatter());
log.addHandler(handler);
log.severe("hello,severe");
log.warning("hello,warning");
log.info("hello,info");
log.config("hello,config");
}
这段代码会将日志信息通过FileHandler
处理器输出到指定的文件中去,默认存储格式为XML,通过添加格式化器handler.setFormatter(new SimpleFormatter());
来重新定义存储格式。
过滤器
每个日志记录器和日志处理器都有一个设置过滤器的函数,且同一时刻只能有一个过滤器。
实例代码:
public static void main(String[] args) throws IOException {
log.setLevel(Level.CONFIG);
//设置不使用父日志记录器的处理器
log.setUseParentHandlers(false);
//为日志记录器指定一个日志处理器
var handler = new FileHandler("/Users/c/Desktop/file%u.log");
handler.setLevel(Level.CONFIG);
//默认为xml格式输出,这里修改为不用xml
handler.setFormatter(new SimpleFormatter());
//为日志处理器添加日志过滤器
handler.setFilter((r) -> {
if(r.getMessage().equals("hhh")){
return true;
}else{
return false;
}
});
log.addHandler(handler);
log.severe("hello,severe");
log.warning("hello,warning");
log.info("hello,info");
log.config("hello,config");
}
setFilter()
可以为记录器或处理器添加一个过滤器,传入定义的Filter对象。根据传入对象中重写的isLoggable()
方法返回的boolean类型结果来决定是否要记录或输出当前日志信息。