日志框架-JUL 日志框架(学习记录二)

本文介绍了Java原生的日志框架JUL,包括Logger、Handler、Filter、Formatter和Level等组件,提供了实战案例展示日志记录、自定义日志级别、日志输出到文件以及使用配置文件定制日志的行为。此外,还讨论了Logger的父子关系和日志配置文件的使用。
摘要由CSDN通过智能技术生成

1、简单介绍

JUL(Java Util Logging),它是 Java 原生的日志框架,位于 java.util.logging.Logger 包。相对其他的框架使用方便,学习简单,主要是使用在小型项目中。

2、组件介绍

组件描述
Logger(记录器)用于记录系统或应用程序的消息,是访问日志系统的入口程序
Handler(处理器)从记录器获取日志消息并输出,决定日志记录最终的输出位置:控制台、文件
Filter(过滤器)用于对记录的内容提供细粒度控制,超出日志级别提供的控制
Formatter(格式器)提供对日志记录格式化的支持,决定日志记录最终的输出形式
Level(日志级别)定义了一组标准的日志记录级别,可用于控制日志记录的输出详解

3、实战案列

导入依赖:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

代码示例:

package com.xb;

import org.junit.Test;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @ClassName:JULTest
 * @Author: xb
 * @Date: 2023/6/4 14:12
 * @Description: TODO
 * @Version 1.0
 */
public class JULTest {

    @Test
    public void test01(){
        // 引入当前类的全路径字符串获取日志记录器
        Logger logger = Logger.getLogger("com.xb.JULTest");

        // 对于日志的输出有两种方式
        // 1、直接调用日志级别的相关方法,方法中传递日志输出信息
        logger.info("info信息1");

        // 2、调用log方法,通过Level类型定义日志级别参数,以及搭配日志输出信息的参数
        logger.log(Level.INFO, "info信息2");

        System.out.println("--------");

        // 打印日志信息并传参
        // 输出学生信息:姓名、年龄
        String name = "张三";
        int age = 23;
        logger.log(Level.INFO, "方式一:学生姓名:" + name + ",学生年龄:" + age);
        logger.log(Level.INFO,"方式二:学生的姓名:{0},年龄:{1}",new Object[]{name,age});
        // 以上操作中,对于输出消息用字符串拼接弊端很多。拼接麻烦、程序效率低、可读性不强、维护成本高
        // 应该使用动态生成数据的方式生产日志,就是占位符的方式来进行操作
    }
}

 运行结果:

六月 04, 2023 2:22:40 下午 com.xb.JULTest test01
信息: info信息1
六月 04, 2023 2:22:40 下午 com.xb.JULTest test01
信息: info信息2
--------
六月 04, 2023 2:22:40 下午 com.xb.JULTest test01
信息: 方式一:学生姓名:张三,学生年龄:23
六月 04, 2023 2:22:40 下午 com.xb.JULTest test01
信息: 方式二:学生的姓名:张三,年龄:23

4、日志级别 

日志级别数值说明
OFFInteger.MAX_VALUE关闭所有消息的日志记录
SEVERE1000错误信息(最高级的日志级别
WARNING900警告信息
INFO(默认)800默认信息(默认级别)
CONFIG   700配置信息
FINE500详细信息(少)
FINER400详细信息(中)
FINEST300详细信息(多)(最低级的日志级别)
ALLInteger.MIN_VALUE启用所有消息的日志记录

 这个数值的意义在于,设置的日志级别是 INFO 级别 - 800 时,则最终展现的日志信息,必须是数值大于 800 的所有级别信息

代码示列:

    @Test
    public void test02() {
        // 获取日志记录器
        Logger logger = Logger.getLogger("com.xb.JulTest");
        // 设置日志级别为配置级别
        logger.setLevel(Level.CONFIG);
        // 输出日志信息
        logger.severe("severe:错误信息");
        logger.warning("warning:警告信息");
        logger.info("info:默认信息");
        logger.config("config:配置信息");
        logger.fine("fine:详细信息(少)");
        logger.finer("finer:详细信息(中)");
        logger.finest("finest:详细信息(多)");
    }

运行结果:

  • 通过打印结果看到只输出了 INFO 级别以及比 INFO 级别高的日志信息,而比 INFO 级别低的日志信息没有打印,说明 INFO 级别的日志信息是系统默认的日志级别。
  • 仅通过以上形式来设置日志级别是不够的,还需要搭配处理器 handler 共同设置才会生效。
六月 04, 2023 2:46:47 下午 com.xb.JULTest test02
严重: severe:错误信息
六月 04, 2023 2:46:47 下午 com.xb.JULTest test02
警告: warning:警告信息
六月 04, 2023 2:46:47 下午 com.xb.JULTest test02
信息: info:默认信息

5、自定义日志级别 

代码示列:需要搭配处理器 handler 共同设置才会生效。

@Test
    public void test03(){
        //获取日志记录器
        Logger logger = Logger.getLogger("com.xb.JULTest");
        //关闭默认的日志打印方式
        logger.setUseParentHandlers(false);
        //控制台处理器
        ConsoleHandler handler = new ConsoleHandler();
        //创建日志格式化组件对象
        SimpleFormatter formatter = new SimpleFormatter();
        //将格式化对象设置
        handler.setFormatter(formatter);
        //在记录器中添加处理器
        logger.addHandler(handler);
        //设置日志打印级别
        //必须将记录器和处理器的级别设置一样,才会出现效果
        handler.setLevel(Level.CONFIG);
        logger.setLevel(Level.CONFIG);
        // 输出日志信息
        logger.severe("severe:错误信息");
        logger.warning("warning:警告信息");
        logger.info("info:默认信息");
        logger.config("config:配置信息");
        logger.fine("fine:详细信息(少)");
        logger.finer("finer:详细信息(中)");
        logger.finest("finest:详细信息(多)");
    }

运行结果:

六月 04, 2023 2:56:49 下午 com.xb.JULTest test03
严重: severe:错误信息
六月 04, 2023 2:56:49 下午 com.xb.JULTest test03
警告: warning:警告信息
六月 04, 2023 2:56:49 下午 com.xb.JULTest test03
信息: info:默认信息
六月 04, 2023 2:56:49 下午 com.xb.JULTest test03
配置: config:配置信息

6、打印日志信息到文件

代码演示:

@Test
    public void test04() throws IOException {
        Logger logger = Logger.getLogger("com.xb.JULTest");
        logger.setUseParentHandlers(false);
        FileHandler handler = new FileHandler("src\\jul.log");
        SimpleFormatter formatter = new SimpleFormatter();
        handler.setFormatter(formatter);
        logger.addHandler(handler);

        logger.setLevel(Level.ALL);
        handler.setLevel(Level.ALL);

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

    }

运行结果:此时控制台中并没有输出日志信息,打开 jul.log 文件,日志信息打印到文件中了。

六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
严重: severe:错误信息
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
警告: warning:警告信息
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
信息: info:默认信息
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
配置: config:配置信息
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
详细: fine:详细信息(少)
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
较详细: finer:详细信息(中)
六月 04, 2023 3:05:38 下午 com.xb.JULTest test04
非常详细: finest:详细信息(多)

添加多个处理器:就是多创建Handel被记录器添加。用户使用 Logger 来进行日志的记录,使用 Handler 来进行日志的输出,Logger 可以持有多个处理器 Handler,添加了哪些 Handler 对象,就相当于根据所添加的 Handler 将日志输出到指定的位置上,例如控制台、文件中…

7、记录器父子关系

JUL 中 Logger 记录器之间是存在 “父子” 关系的,这种父子关系不是我们普遍认为的类之间的继承关系,关系是通过树状结构存储的。
JUL 在初始化时会创建一个顶层 RootLogger 作为所有 Logger 的父 Logger,RootLogger 是 LogManager 的内部类,默认的名称为空串。
以上的 RootLogger 对象作为树状结构的根节点存在的,将来自定义的父子关系通过路径来进行关联,父子关系同时也是节点之间的挂载关系。
代码演示:

 @Test
    public void test05() {
        // 创建两个 logger 对象,可以认为 logger1 是 logger2 的父亲
        // RootLogger 是所有 logger 对象的顶层 logger,名称默认是一个空的字符串
        Logger logger1 = Logger.getLogger("com.xb");
        Logger logger2 = Logger.getLogger("com.xb.JulTest");

        System.out.println(logger2.getParent() == logger1);
        System.out.println("----");

        System.out.println("logger1名称:" + logger1.getName() +
                ",\n父Logger名称:" + logger1.getParent().getName() +
                ",\n父Logger引用:" + logger1.getParent());
        System.out.println("----");

        System.out.println("logger2名称:" + logger2.getName() +
                ",\n父Logger名称:" + logger2.getParent().getName() +
                ",\n父Logger引用:" + logger2.getParent());
        System.out.println("----");

        // 父亲所做的设置,也能够同时作用于儿子
        // 对 logger1 做日志打印相关的设置,然后我们使用 logger2 进行日志的打印
        logger1.setUseParentHandlers(false);

        ConsoleHandler handler = new ConsoleHandler();
        SimpleFormatter formatter = new SimpleFormatter();
        handler.setFormatter(formatter);
        logger1.addHandler(handler);
        handler.setLevel(Level.ALL);
        logger1.setLevel(Level.ALL);

        //儿子做打印
        logger2.severe("severe:错误信息");
        logger2.warning("warning:警告信息");
        logger2.info("info:默认信息");
        logger2.config("config:配置信息");
        logger2.fine("fine:详细信息(少)");
        logger2.finer("finer:详细信息(中)");
        logger2.finest("finest:详细信息(多)");
    }

运行结果:Root设置级别,你会发现log2受到影响

true
----
logger1名称:com.xb,
父Logger名称:,
父Logger引用:java.util.logging.LogManager$RootLogger@15327b79
----
logger2名称:com.xb.JulTest,
父Logger名称:com.xb,
父Logger引用:java.util.logging.Logger@4f2410ac
----
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
严重: severe:错误信息
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
警告: warning:警告信息
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
信息: info:默认信息
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
配置: config:配置信息
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
详细: fine:详细信息(少)
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
较详细: finer:详细信息(中)
六月 04, 2023 3:19:15 下午 com.xb.JULTest test05
非常详细: finest:详细信息(多)

8、日志的配置文件

以上所有配置的相关操作,都是以 java 硬编码的形式进行的,我们可以使用配置文件,若没有指定自定义日志配置文件,则使用系统默认的日志配置文件。

默认配置文件位置: jdk 安装目录下 \ jre \ lib \ logging.properties 文件 。

默认配置:

############################################################
#  	默认日志记录配置文件
#
# 您可以通过使用java.util.logging.config.file系统属性指定文件名来使用不同的文件
# 例如 java -Djava.util.logging.config.file=myfile
############################################################

############################################################
#  	全局性质
############################################################

# RootLogger使用的处理器,在获取RootLogger对象时进行的设置
# 可在当前处理器类后,通过指定的英文逗号分隔,添加多个日志处理器
# 这些处理程序将在VM启动期间安装,请注意:这些类必须位于系统类路径上
# 默认情况下,只配置控制台处理程序,默认打印INFO和高于INFO级别消息
handlers = java.util.logging.ConsoleHandler

# 要添加文件处理程序,请使用以下行(多个日志处理器)
#handlers= java.util.logging.FileHandler, java.util.logging.ConsoleHandler

# RootLogger 默认的全局日志记录级别
# 对于这种全局层面的任何特定配置,可以通过配置特定的水平来覆盖
# 如果不手动配置其它的日志级别,则默认输出下述配置的级别以及更高的级别
.level = INFO

############################################################
# 处理器指定属性,描述处理程序的特定配置信息
############################################################

# 文件处理器属性设置
# 默认输出的日志文件路径,位于用户的主目录中
# %h:当前用户系统的默认根路径,C:\用户\用户名\java0.log
# %u:指向默认输出的日志文件数量count,count=1,则:java0.log;count=2,则:java0.log,java1.log...
java.util.logging.FileHandler.pattern = %h/java%u.log
# 默认输出的日志文件大小(单位字节)
java.util.logging.FileHandler.limit = 50000
# 默认输出的日志文件数量
java.util.logging.FileHandler.count = 1
# 默认输出的日志文件格式(XML)
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# 控制台处理器属性设置
# 默认输出的日志级别
java.util.logging.ConsoleHandler.level = INFO
# 默认输出的日志格式(Simple)
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# 示例以自定义简单的格式化器输出格式,以打印这样的单行日志消息:
#     <level>: <log message> [<date/time>]
#
# java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n

############################################################
# 配置特定属性,为每个记录器提供额外的控制
############################################################

# 例如:将日志级别设定到具体的某个包下
com.xyz.foo.level = SEVERE

9、自定义配置文件

创建好配置文件:logging.properties 文件,修改好里面的内容

代码:

// 自定义配置文件
@Test
public void test07() throws IOException {
    // 读取自定义日志配置文件
    InputStream input = new FileInputStream("src/logging.properties");
    // 获取日志管理器
    LogManager logManager = LogManager.getLogManager();
    // 日志管理器读取自定义配置文件
    logManager.readConfiguration(input);
    // 日志记录器
    Logger logger = Logger.getLogger("com.xb.JulTest");
    // 输出日志信息
    logger.severe("severe:错误信息");
    logger.warning("warning:警告信息");
    logger.info("info:默认信息");
    logger.config("config:配置信息");
    logger.fine("fine:详细信息(少)");
    logger.finer("finer:详细信息(中)");
    logger.finest("finest:详细信息(多)");
}

追加日志信息:

# 默认输出的日志内容会覆盖上次输出的内容, 设为true改为追加
java.util.logging.FileHandler.append=true

10、JUL原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值