JUL日志实现框架:配置文件

目录

前言

顶级父元素RootLogger 默认设置

▎debug断点测试

自定义logging.properties文件

▎ConsoleHandler 配置

★ SimpleFormatter数据转换  

▎FileHandler 配置

✷ 存在问题:日志内容覆盖


前言

我们知道自己创建的logger对象,没有继承父元素的话,那其顶级父元素默认就是RootLogger ,它默认日志级别是info,使用的是ConsoleHandler处理器,数据转换用的是SimpleFormatter格式化组件,而这些配置需要我们通过硬编码方式修改,这种方式不太方便后期的管理和维护,因此我们可以通过配置文件的方式进行设置

顶级父元素RootLogger 默认设置

RootLogger对象默认的加载就是配置文件方式,我们可以来通过源码进行查看

1. 获取logger对象时,通过调用 getLogger 构造函数,得到logger实例对象

Logger logger1 = Logger.getLogger("com");

2. 该构造函数底部实际调用的是demandLogger()方法

3. 其方法内部的第一件事就是 获取 LogManager.getLogManager(); 日志管理器对象

4. 日志管理器是一个单例对象,用于加载配置文件的,其内部调用了ensureLogManagerInitialized

5. 继续翻看ensureLogManagerInitialized方法的代码,可以看到有读取配置文件的方法,如下图

6. 俄罗斯套娃,继续点进去查看

7. readConfiguration() 方法,首先会加载,你当前系统类是否有配置类,如果有,则直接加载

8. 如果没有配置类,下方会继续判断,你是否有自定义的配置文件,如果有,则加载你的配置文件,如果还是没有,那么会默认加载 java.home 下的lib文件夹中的 logging.properties 文件

debug断点测试

1. 我们在方法内部,读取配置文件位置处进行断点,因为我们没有logger的配置类和自定义配置文件,因此会默认加载java.home文件目录下的文件

2. 使用debug模式运行上述父子类继承特性的测试方法

如下代码在上篇博文《Logger 对象使用详解》中,继承特性里详细贴出来过,主要代码是设置一个logger对象的父类,并修改父类的配置,例如日志级别等,然后通过子类打印日志信息,测试子类继承父类的特性

3. 进入debug代码,可以看到默认配置文件的目录

4. 复制该路径地址,打开访达,Command + shift+G 快捷键,进行搜索该目录

5. 进入lib 目录,找到logging.properites文件,右键打开

6. 配置文件参数如下



# RootLogger顶级父元素指定的默认处理器为:ConsoleHandler和FileHandler(多个处理器之间用逗号隔开)
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

# RootLogger顶级父元素默认的日志级别为:ALL
.level= ALL


# -------------------- 向文件输出的handler对象--------------------

# 指定日志文件路径:%h 当前用户目录,文件名以java开始,%u 是以数字取值
java.util.logging.FileHandler.pattern = %h/java%u.log
# 指定日志文件内容大小,最大为5w条日志
java.util.logging.FileHandler.limit = 50000
# 指定日志文件数量:如果设置为10,则pattern日志文件的命名中的%u取值是 0-9之间
java.util.logging.FileHandler.count = 1
# 指定日志消息格式对象:日志内容将以XML的形式输出到文件中
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter




# -------------------- 向控制台输出的handler对象--------------------

# 指定 handler 对象的日志级别
java.util.logging.ConsoleHandler.level = ALL
# 指定日志消息格式对象:日志内容是简单的文字信息
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

自定义logging.properties文件

上述说了,硬编码的方式配置日志参数,不便于后期维护,因此我们可以通过自定义配置文件方式来加载logger的配置参数

1. 创建日志配置文件,将上述的java.home/lib 目录下的 logging.properties 配置文件复制到resource目录,加以修改即可

2. 编写测试类,进行测试

// 测试resources目录下自定义logging配置文件
@Test
public void test07() throws IOException {

        // 1.使用当前类的类加载器读取自定义日志配置文件
        InputStream resourceAsStream = LogDemo.class.getClassLoader().getResourceAsStream("logging.properties");

        // 2.获取日志管理器(LogManager是单例对象,直接获取即可)
        LogManager logManager = LogManager.getLogManager();

        // 3.通过日志管理器调用读取配置文件方法
        logManager.readConfiguration(resourceAsStream);


        // 日志记录器
        Logger logger = Logger.getLogger("com.JULTest");

        // 输出日志信息
        logger.severe("severe:错误信息");
        logger.warning("warning:警告信息");
        logger.info("info:默认信息");
        logger.config("config:配置信息");
        logger.fine("fine:详细信息(少)");
        logger.finer("finer:详细信息(中)");
        logger.finest("finest:详细信息(多)");
    }
}

3. 上述测试用例执行结果,下方是ConsoleHandler处理器的执行结果,以标准的日志格式输出到控制台,内部使用的是System.err

4. 由于配置文件中,设置了2个handler处理器,我们再查看FileHandler处理器的输出结果,在当前用户目录下,找到日志文件

该日志文件的命名格式是配置文件中 FileHandler.pattern 参数

5. 点击查看文件内容,以XML格式输出的日志

ConsoleHandler 配置

自定义配置文件中,只设置了日志级别和数据转换类,实际还可以设置其他参数,如编码字符集、过滤器,我们可以通过该类进行查看具体配置参数

例如配置编码字符集

# 指定 handler 对象的日志级别
java.util.logging.ConsoleHandler.level = ALL

# 指定 handler 对象的日志消息格式对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# 指定 handler 对象的字符集编码
java.util.logging.ConsoleHandler.encoding=UTF-8

★ SimpleFormatter数据转换  

格式化组件也可以设置其格式,例如:

配置文件设置方式

# 指定 handler 对象的日志级别
java.util.logging.ConsoleHandler.level = ALL

# 指定 handler 对象的日志消息格式对象
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# 指定 handler 对象的字符集编码
java.util.logging.ConsoleHandler.encoding=UTF-8


# 指定日志消息格式
java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n

执行结果:

FileHandler 配置

同样,除了默认的配置参数之外,还能配置其他额外参数,如下

例如XML的格式输出到文件,不方便查看,我们可以修改数据格式化为简单文字信息

# 指定日志文件路径:%h 当前用户目录,文件名以java开始,%u 是以数字取值
java.util.logging.FileHandler.pattern = %h/java%u.log

# 指定日志文件内容大小,最大为5w条日志
java.util.logging.FileHandler.limit = 50000

# 指定日志文件数量:如果设置为10,则pattern日志文件的命名中的%u取值是 0-9之间
java.util.logging.FileHandler.count = 1

# 指定日志消息格式对象:日志内容将以XML的形式输出到文件中
#java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# 指定日志消息格式对象:日志内容将以文字信息形式输出到文件中
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

执行test07测试用例结果:

存在问题:日志内容覆盖

默认的FileHandler处理器配置没有设置日志内容是追加模式,也就是每次执行新的日志打印,都会覆盖原来的内容,导致日志内容丢失。

我们希望的是,每次日志打印以追加的模式进行记录,当达到配置的最大条数5w条后,才执行日志覆盖,那么可以设置.append参数值,如下

# 指定日志文件路径:%h 当前用户目录,文件名以java开始,%u 是以数字取值
java.util.logging.FileHandler.pattern = %h/java%u.log

# 指定日志文件内容大小,最大为5w条日志
java.util.logging.FileHandler.limit = 50000

# 指定日志文件数量:如果设置为10,则pattern日志文件的命名中的%u取值是 0-9之间
java.util.logging.FileHandler.count = 1

# 指定日志消息格式对象:日志内容将以XML的形式输出到文件中
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter

# 指定以追加方式添加日志内容
java.util.logging.FileHandler.append = true

执行结果:两次运行的日志都被记录下来了,而不是像之前一样覆盖原日志信息

自定义logger对象配置

1. 增加自定义logger对象的配置,如果不自定义,默认使用的是父元素,即RootLogger

# RootLogger顶级父元素指定的默认处理器为:ConsoleHandler和FileHandler(多个处理器之间用逗号隔开)
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

# RootLogger顶级父元素默认的日志级别为:ALL
.level= ALL

# 自定义logger使用:自定义一个名为com.JULTest的logger对象的配置参数
com.JULTest.handlers = java.util.logging.ConsoleHandler
com.JULTest.level = WARNING

# 关闭默认配置:关闭com.JULTest的父类继承特性
com.JULTest.useParentHandlers = false

2. 测试类进行测试

// 测试resources目录下自定义logging配置文件
@Test
public void test07() throws IOException {

        // 1.使用当前类的类加载器读取自定义日志配置文件
        InputStream resourceAsStream = LogDemo.class.getClassLoader().getResourceAsStream("logging.properties");

        // 2.获取日志管理器(LogManager是单例对象,直接获取即可)
        LogManager logManager = LogManager.getLogManager();

        // 3.通过日志管理器调用读取配置文件方法
        logManager.readConfiguration(resourceAsStream);


        // 日志记录器:com.JULTest我们在自定义配置文件配置日志级别为warning
        Logger logger = Logger.getLogger("com.JULTest");

        // 输出日志信息
        logger.severe("severe:错误信息");
        logger.warning("warning:警告信息");
        logger.info("info:默认信息");
        logger.config("config:配置信息");
        logger.fine("fine:详细信息(少)");
        logger.finer("finer:详细信息(中)");
        logger.finest("finest:详细信息(多)");

        // 日志记录器:默认继承了父元素RootLogger的特性
        Logger logger2 = Logger.getLogger("mytest");

        // 输出日志信息
        logger2.severe("severe:错误信息 mytest");
        logger2.warning("warning:警告信息 mytest");
        logger2.info("info:默认信息 mytest");
        logger2.config("config:配置信息 mytest");
        logger2.fine("fine:详细信息(少) mytest");
        logger2.finer("finer:详细信息(中) mytest");
        logger2.finest("finest:详细信息(多) mytest");
}

执行结果:

分析:配置文件设置了 RootLogger元素的日志级别为ALL,而 mytest 的logger实例对象继承了父元素RootLogger的特性,因此日志全部打印了,而名为 com.JULTest 的logger实例,在配置文件中设置的日志级别为warning,因此大于warning级别的日志会被打印出来,所以只有2条输出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值