Java日志框架 -- 日志框架介绍、日志门面技术、JUL日志(JUL架构、JUL入门示例、JUL日志级别、JUL日志的配置文件)

1. 日志的概念

日志文件是用于记录系统操作事件的文件集合,可分为事件日志消息日志。具有处理历史数据、诊断问题的追踪以及理解系统的活动等重要作用。


2. Java日志框架

问题:

  1. 控制日志输出的内容和格式。
  2. 控制日志输出的位置。
  3. 日志优化:异步日志,日志文件的归档和压缩。
  4. 日志系统的维护。
  5. 面向接口开发 :日志的门面。

2.1 为什么要用日志框架

因为软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。而且框架一般是成熟,稳健的,他可以处理系统很多细节问题,比如,事务处理,安全性,数据流控制等问题。还有框架一般都经过很多人使用,所以结构很好,所以扩展性也很好,而且它是不断升级的,你可以直接享受别人升级代码带来的好处。


2.2 现有的日志框架

  • JUL(java util logging)
  • logback
  • log4j
  • log4j2
  • JCL(Jakarta Commons Logging)
  • slf4j( Simple Logging Facade for Java)

日志门面(抽象层):是日志实现的抽象类。有JCL、SLF4J

  • JCL:当时设计时只考虑了主流的几个日志框架,而对于未来新兴框架并没有提供接口,之后随着slf4j出现就慢慢也不再使用了,最后一次版本更新停在2014年,现不再更新维护已被淘汰,不考虑使用。
  • slf4j:能够统一管理所有的日志API,优秀的门面技术,并且其能够支持未来出现的新的日志框架系统并提供日志接口。Springboot推荐slf4j+logback,未来主流会是slf4j+log4j2

日志实现:具体的日志功能实现。框架有JUL、log4j、log4j2、logback。

  • JUL:JDK自带的日志实现依赖。
  • logback:第三方的,Springboot默认推荐,搭配slf4j。
  • log4j:Apache推出的,之后出现了Logback(性能更好),就开始慢慢被Logback取代了。
  • log4j2:Apache根据Logback的设计思想推出了Log4j2,号称日志性能最好的实现技术,其本身也有日志门面只不过大多使用slf4j来作为日志门面。

日志框架出现的历史顺序:

log4j -->JUL-->JCL--> slf4j --> logback --> log4j2

2.3 日志门面技术介绍

当我们的系统变的更加复杂的时候,我们的日志就容易发生混乱。随着系统开发的进行,可能会更新不同的日志框架,造成当前系统中存在不同的日志依赖,让我们难以统一的管理和控制。就算我们强制要求所有的模块使用相同的日志框架,系统中也难以避免使用其他类似spring,mybatis等其他的第三方框架,它们依赖于我们规定不同的日志框架,而且他们自身的日志系统就有着不一致性,依然会出来日志体系的混乱。

所以我们需要借鉴JDBC的思想,为日志系统也提供一套门面,那么我们就可以面向这些接口规范来开发,避免了直接依赖具体的日志框架。这样我们的系统在日志中,就存在了日志的门面和日志的实现。


2.3.1 日志门面技术的优点

  1. 面向接口开发,不再依赖具体的实现类。减少代码的耦合
  2. 项目通过导入不同的日志实现类,可以灵活的切换日志框架
  3. 统一API,方便开发者学习和使用
  4. 统一配置便于项目日志的管理

2.3.2 日志门面和日志实现的关系

在这里插入图片描述

用户可以使用日志门面,然后根据需求,动态的选择具体的日志实现框架。这样就可以使所有日志实现框架拥有统一的规范。


3. JUL


3.1 JUL架构介绍

在这里插入图片描述

  • Loggers:被称为记录器,应用程序通过获取Logger对象,调用其API来来发布日志信息。Logger通常时应用程序访问日志系统的入口程序
  • Appenders:也被称为Handlers,每个Logger都会关联一组Handlers,Logger会将日志交给关联Handlers处理,由Handlers负责将日志做记录。Handlers在此是一个抽象,其具体的实现决定了日志记录的位置可以是控制台、文件、网络上的其他日志服务或操作系统日志等。
  • Layouts:也被称为Formatters,它负责对日志事件中的数据进行转换和格式化。Layouts决定了数据在一条日志记录中的最终形式。
  • Level:每条日志消息都有一个关联的日志级别。该级别粗略指导了日志消息的重要性和紧迫,我可以将Level和Loggers,Appenders做关联以便于我们过滤消息。
  • Filters:过滤器,根据需要定制哪些信息会被记录,哪些信息会被放过。

小结:用户使用Logger来进行日志记录,Logger持有若干个Handler,日志的输出操作是由Handler完成的。在Handler在输出日志前,会经过Filter的过滤,判断哪些日志级别过滤放行哪些拦截,Handler会将日志内容输出到指定位置(日志文件、控制台等)。Handler在输出日志时会使用Layout,将输出内容进行排版。


3.2 JUL入门示例


3.2.1 创建普通Maven项目,导入Junit单元测试依赖

在这里插入图片描述


3.2.2 编写测试代码

在这里插入图片描述

JULTest.java

package logs;

import org.junit.Test;

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

public class JULTest {
    @Test
    public void testQuick() throws Exception {
        // 1. 创建日志记录器对象, 每个记录器都有自己唯一的标识 一般是当前类的全限定类名作为标识
        Logger logger = Logger.getLogger("logs.JULTest");
        // 2. 日志记录输出
        logger.info("hello jul");
        // 3. 通用的方法进行日志的记录
        logger.log(Level.INFO, "info msg");
        String name = "jack";
        Integer age = 18;
        // 通过占位符数据变量的值
        logger.log(Level.INFO, "用户信息:{0} ,{1}", new Object[]{name, age});
    }
}

运行结果:
在这里插入图片描述


3.3 JUL日志的级别

JUL中定义的日志级别在Level当中:
在这里插入图片描述

下面我们来看看JUL日志的级别:
在这里插入图片描述
在这里插入图片描述


3.4 自定义日志级别配置

在这里插入图片描述

JULTest.java

    @Test
    public void testLogConfig() throws Exception {
        // 1.创建日志记录器对象
        Logger logger = Logger.getLogger("logs.JULTest");
        // 一、自定义日志级别
        // a.关闭系统默认配置
        logger.setUseParentHandlers(false);
        // b.创建handler对象 把日志输出到控制台
        ConsoleHandler consoleHandler = new ConsoleHandler();
        // c.创建formatter对象
        SimpleFormatter simpleFormatter = new SimpleFormatter();
        // d.进行关联
        consoleHandler.setFormatter(simpleFormatter);
        logger.addHandler(consoleHandler);
        // e.设置日志级别
        logger.setLevel(Level.ALL);
        consoleHandler.setLevel(Level.ALL);

        // 二、输出到日志文件
        FileHandler fileHandler = new FileHandler("./jul.log");
        fileHandler.setFormatter(simpleFormatter);
        logger.addHandler(fileHandler);

        // 2.日志记录输出
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

运行结果:
在这里插入图片描述
在这里插入图片描述


3.5 Logger之间的父子关系

JUL中Logger之间存在父子关系,这种父子关系通过树状结构存储,JUL在初始化时会创建一个顶层RootLogger作为所有Logger父Logger,存储上作为树状结构的根节点。并父子关系通过路径来关联。

测试代码:

    @Test
    public void testLogParent() throws Exception {
        // 日志记录器对象父子关系
        Logger logger1 = Logger.getLogger("com.tian.log");
        Logger logger2 = Logger.getLogger("com.tian");

        // 返回True则表示logger1是logger2的孩子
        System.out.println(logger1.getParent() == logger2);
        // 所有日志记录器对象的顶级父元素 class为java.util.logging.LogManager$RootLogger name为""
        System.out.println("logger2 parent:" + logger2.getParent() + ",name:" + logger2.getParent().getName());
    }

运行结果:

在这里插入图片描述


3.6 日志的配置文件

默认配置文件路径:$JAVAHOME\jre\lib\logging.properties

我们现在来自定义配置文件进行测试
测试代码:
在这里插入图片描述
JULTest.java

    @Test
    public void testProperties() throws Exception {
        // 读取自定义配置文件
        InputStream in = JULTest.class.getClassLoader().getResourceAsStream("logging.properties");
        // 获取日志管理器对象
        LogManager logManager = LogManager.getLogManager();
        // 通过日志管理器加载配置文件
        logManager.readConfiguration(in);

        Logger logger = Logger.getLogger("com.tian.JULTest");
        logger.severe("severe");
        logger.warning("warning");
        logger.info("info");
        logger.config("config");
        logger.fine("fine");
        logger.finer("finer");
        logger.finest("finest");
    }

自定义配置文件位置
在这里插入图片描述logging.properties

## RootLogger使用的处理器(获取时设置)
handlers=java.util.logging.ConsoleHandler
# RootLogger日志等级
.level=INFO
## 自定义Logger
com.tian.handlers=java.util.logging.FileHandler
# 自定义Logger日志等级
com.tian.level=INFO
# 忽略父日志设置
com.tian.useParentHandlers=false
## 控制台处理器
# 输出日志级别
java.util.logging.ConsoleHandler.level=INFO
# 输出日志格式
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
## 文件处理器
# 输出日志级别
java.util.logging.FileHandler.level=INFO
# 输出日志格式
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
# 输出日志文件路径
java.util.logging.FileHandler.pattern=C:/logs/java.log
# 输出日志文件限制大小(50000字节)
java.util.logging.FileHandler.limit=50000
# 输出日志文件限制个数
java.util.logging.FileHandler.count=1
# 输出日志文件 是否是追加
java.util.logging.FileHandler.append=false

运行结果:
在这里插入图片描述

在这里插入图片描述



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodeJiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值