java 自带的日志系统

目录

1、全局日志记录器

2、自定义日志记录器

3、日志系统的配置文件

4、日志处理器

4.1 ConsoleHandler控制台处理器

4.2 FileHandler文件处理器 和 SocketHandler套接字处理器

5、日志过滤器

6、格式化器


java提供了日志的API,首先看一下这些API有哪些作用:

1、打开、关闭日志,设置日志的记录级别;

2、日志可以被定向到不同的处理器;

3、日志记录器和处理器都可以对日志记录进行过滤。

4、日志记录可以采用不同的方式格式化;

5、应用程序可以使用多个日志记录器;

6、默认情况下,日志系统的配置是由配置文件控制的,可以改变这个配置;

日志记录器:负责记录日志消息;

日志处理器:不能光记录日志,有时候需要处理日志;

日志过滤器:有时候,我们只想记录我们想要的那些日志消息,对于其它没有用的日志消息,我们不想记录它,免得浪费资源,于是过滤器就可以设置过滤条件,对符合条件的日志消息才进行记录。

再说说日志级别(从大到小),默认是INFO级别:SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST。

设置了日志级别之后,能记录的消息级别必须是超过或等于该级别的,比如设置为INFO,那么就只能记录INFO,WARNING,SEVERE。

1、全局日志记录器

我们先来体会一下日志,代码如下:

public class test {
    public static void main(String[] args){
        Logger logger = Logger.getGlobal();  //java.util.logging.Logger
        logger.info("哈哈哈哈");
    }
}

运行结果:

用Logger.getGlobal() 方法得到的对象就是java日志系统默认使用的全局日志记录器。即单例模式,在任何地方调用Logger.getGlobal()方法得到的对象都是同一个。可以看出记录的日志信息包括:时间、类名、方法名、日志内容。

2、自定义日志记录器

如果一个项目中,有多个地方需要日志记录,但是这些地方对日志的要求又不同,那么就需要自定义多个日志记录器。

Logger logger = Logger.getLogger("name");
logger.info("hello");

设置自定义记录器的名字,然后直接使用记录器即可。名字是有讲究的,可以用名字表示父子关系,属性还可以继承,如下所示。如果两个日志记录器名字是一样的,那么得到的对象是同一个对象。

Logger log = Logger.getLogger("aaa");
log.setLevel(Level.WARNING);
Logger logger1 = Logger.getLogger("aaa.haha");
logger1.info("hahhaha'ehhe");

分析:info是打印不出来的,因为INFO的级别低于WARNING ,然而logger1记录器是继承于log记录器的。

3、日志系统的配置文件

日志有一套框架(即被人叫做系统),那总有一些默认配置吧,就有一个配置文件,在jre / conf / logging.properties。里面可以设置默认日志级别、处理器已经处理器的配置等等。还有,日志管理器是在vm启动过程中初始化的,在main执行之前。

但是我们有时候不想修改默认配置文件,只是想写一个新的配置文件,如何让新配置文件起作用呢?

首先,把新文件放在jre / conf / 目录下面,然后在启动应用程序时,使用命令:java -Djava.util.logging.config.file=新文件名 应用程序名     。

默认配置文件如下:

# 这是默认的处理器(控制台处理器),这就是为什么我们的日志信息会在控制台里面显示出来
handlers= java.util.logging.ConsoleHandler

# 如果想用的默认处理器不止这一个的话,就可以使用下列的配置方式增加.
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# 默认的全局日志级别.
.level= INFO

# 日志文件默认存储的位置和文件名.
java.util.logging.FileHandler.pattern = %h/java%u.log
# 单个日志文件允许存储的最大字节数,0表示无限,如果超过了的话,就会重新覆盖掉之前的内容
java.util.logging.FileHandler.limit = 50000
# 日志文件的个数,1表示就一个文件,如果是多个文件的话,会循环地存储,满一个再存下一下,如果都满
#了,就删除最旧的文件,创建一个新文件代替旧文件,再从头开始存储
java.util.logging.FileHandler.count = 1
# 处理器获取锁文件的最大尝试次数.
java.util.logging.FileHandler.maxLocks = 100
# 日志文件的格式,下面这个就是xml的格式
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# 显示在控制台里面的日志的最低级别.
java.util.logging.ConsoleHandler.level = INFO
# 显示在控制台里面的日志格式
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# 还可以对其他处理器、记录器设置额外的属性,下面仅仅是个例子
com.xyz.foo.level = SEVERE

4、日志处理器

处理器仍然有日志级别这个属性,表示什么级别以上的日志消息才能被处理。

4.1 ConsoleHandler控制台处理器

日志记录器负责记录日志,但是如何处理日志就是处理器的事情了。默认情况下,记录器都要将记录发送给处理器ConsoleHandler,ConsoleHandler处理器则将日志消息打印在控制台中。

日志记录器是有父子关系的,所以日志记录器除了要将日志消息发送给自己的处理器外,还要发送给自己父记录器的处理器。

举个例子:

Logger log = Logger.getLogger("aaa");
log.setLevel(Level.WARNING);
Handler handler = new ConsoleHandler();
log.addHandler(handler);
log.warning("哈哈哈");

运行结果:

分析:打印了两次日志信息,怎么回事呢?因为log记录器将日志消息发送给自己的处理器handler,打印了一次,另外,还发送给了自己的父类记录器(根记录器)的处理器(还是一个ConsoleHandler),所以又打印了一次。

为了不重复打印,就禁用父处理器,如下:

Logger log = Logger.getLogger("aaa");
log.setLevel(Level.WARNING);
Handler handler = new ConsoleHandler();
log.addHandler(handler);
log.setUseParentHandlers(false);
log.warning("哈哈哈");

4.2 FileHandler文件处理器 和 SocketHandler套接字处理器

一旦将FileHandler设置给日志记录器之后,日志消息就会存储到文件里,至于存储的策略和存储到哪,日志系统的配置文件已经设置得很清楚了。对于pattern这个属性里面的符号含义,如下:

套接字处理器就是日志记录器直接将日志消息发送到某个主机端口。

5、日志过滤器

默认情况下,不就是根据日志记录器和日志处理器的级别来进行过滤吗?但是这样是一般的过滤方式,如果我们还想过滤得更细化一些呢(过滤具体的内容)。java.util.logging包下面有一个接口(如下),但是未提供任何实现类,所以要自己实现:

public interface Filter {
    //LogRecord是日志消息类,用于对应一条日志消息,
    //isLoggable方法是检查日志消息是否满足我们的过滤条件,如果满足,就返回true,表示此日志应该被
    //记录下,如果是false,就丢掉即可,当然,具体的过滤代码根据自己的需求自己实现
    public boolean isLoggable(LogRecord record);
}

log.setFilter() 就可以为我们的记录器设置过滤器了,handler.setFilter()为处理器设置过滤器。

注意:同一时刻,最多只能有一个过滤器进行过滤。

6、格式化器

java自带日志系统就提供了三种日志格式,SimpleFormatter是控制台输出的那种格式,XMLFormatter是xml格式,HttpLogFormatter是适用http传输的格式:

所以如果我们要自定义日志的格式,就需要自己实现Formatter抽象类,一共可实现三个方法:

String format(LogRecord record)方法:对记录中的信息进行格式化,返回结果字符串

String getHead(Handler h)方法 和 String getTail(Handler h)方法:如果需要的话,这两个方法是给已经格式化的记录前后加上一个头部和尾部。

如果大家不知道如何自定义一个格式化器,可以参照SimpleFormatter类,比较简单,容易理解。

 

 

最后,说一下,最好将日志记录器声明为static final的,因为不这样,vm的垃圾回收机制可能会回收掉日志记录器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值