【Log】(一)Java 中的日志框架JUL、Log4j

【Log】(一)Java 中的日志框架 JUL、Log4j
【Log】(二)Java 中的日志框架 JCL、SLF
【Log】(三)Java 中的日志框架 Logback、log4j2


现有的日志框架:

  1. 日志门面:JCL(Jakarta Common Logging)、SLF
  2. 日志实现:JUL(Java Util Logging)、log4j、logback、log4j2

logbacklog4j 功能更加强大,性能更加好;log4j2logback 功能相似,但前者的性能更好

1. JUL 学习

1.1 JUL 介绍

JUL:全称 Java Util Logging,它是 Java 原生的日志框架,使用时不需要引入第三方类库,相对其它日志框架使用方便、学习简单,能够在小型应用中灵活使用。

架构

在这里插入图片描述

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

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

1.2 快速入门

新建一个 SpringBoot 工程,引入一个 junit 依赖,POM 文件:

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

入门案例:

public class JulTest {

	public static final String CALSS_NAME = "com.zzc.sbexp.log.jul.JulTest";

    @Test
    public void testQuick() {
        Logger logger = Logger.getLogger(CALSS_NAME);
        // 输出日志 日志级别:info
        logger.info("hello jul");

        // 通过方法输出
        logger.log(Level.INFO, "hello jul");

        // 通过占位符输出变量值
        String name = "zzc";
        Integer age = 24;
        logger.log(Level.INFO, "用户信息:{0}, {1}", new Object[]{name, age});
    }

}

1.3 日志级别

日志级别从高至低:offserverwarninginfoconfigfinefinerfinestall

如果是:off,那么就是关闭了日志级别输出;
如果是:all,那么就是开启了日志级别输出。

Jul 默认级别是 info,只要日志级别高于 info,都会输出。

自定义日志级别:

步骤:

  1. 关闭系统默认配置
  2. 创建一个 Handler。我这里是输出到控制台和磁盘,所以是 ConsoleHandlerFileHandler
  3. 创建一个 Formatter
  4. HandlerFormatter 进行关联;
  5. Handler 添加到 Logger 中。
@Test
public void testLogConfig() throws IOException {
    Logger logger = Logger.getLogger(CALSS_NAME);
    // 关闭系统默认配置
    logger.setUseParentHandlers(false);
    // 创建控制台输出Handler
    ConsoleHandler consoleHandler = new ConsoleHandler();
    SimpleFormatter simpleFormatter = new SimpleFormatter();
    // 关联
    consoleHandler.setFormatter(simpleFormatter);
    // 创建文件输出Handler
    FileHandler fileHandler = new FileHandler("logs.log");
    fileHandler.setFormatter(simpleFormatter);

    logger.addHandler(consoleHandler);
    logger.addHandler(fileHandler);
    // 配置日志级别
    logger.setLevel(Level.ALL);
    consoleHandler.setLevel(Level.ALL);
    fileHandler.setLevel(Level.WARNING);

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
}

【注意】:logs.log 的父级路径必须得存在,否则,会报错。

自定义配置文件修改 RootLogger 的默认配置:

在 resource 路径下添加一个配置文件 logging.properties,其内容为:

#RootLogger默认的处理器,可以配置多个,所有非手动解除父日志的子日志都将使用这些处理器
handlers= java.util.logging.ConsoleHandler,java.util.logging.FileHandler

#RootLogger的日志级别(默认INFO),所有的Handler都受限于此日志级别,Handler的日志级别可以比RootLogger的日志级别
.level = INFO

java.util.logging.FileHandler.pattern = E:/logs/java%u.log
#单个日志文件大小,单位是bit,1024bit即为1kb
java.util.logging.FileHandler.limit = 1024 * 1024 * 10
#日志文件数量
java.util.logging.FileHandler.count = 1
#是否以追加方式添加日志内容
java.util.logging.FileHandler.append = true
java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.encoding = UTF-8
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

代码:

@Test
public void testLogProperties() throws IOException {
    // 通过类加载加载配置文件
    InputStream in = JulTest.class.getClassLoader().getResourceAsStream("logging.properties");
    // 创建LogManger加载配置文件
    LogManager logManager = LogManager.getLogManager();
    logManager.readConfiguration(in);
    Logger logger = Logger.getLogger(CALSS_NAME);

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
    logger.finest("finest");
}

自定义配置文件添加自定义的 Logger:

在 resource 路径下添加一个配置文件 logging.properties,其内容为:

...

my.logger.handlers = java.util.logging.ConsoleHandler
my.logger.level = INFO
my.logger.useParentHandlers = false

代码:

@Test
public void testMyLogProperties() throws IOException {
    // 通过类加载加载配置文件
    InputStream in = JulTest.class.getClassLoader().getResourceAsStream("logging.properties");
    // 创建LogManger加载配置文件
    LogManager logManager = LogManager.getLogManager();
    logManager.readConfiguration(in);
    Logger logger = Logger.getLogger("my.logger");

    logger.severe("server");
    logger.warning("warning");
    logger.info("info");
    logger.finest("finest");
}

2. Log4j 学习

2.1 Log4j 介绍

Log4jApache 下的一款开源的日志框架,通过在项目中使用 log4j,我们可以控制日志信息输出的位置(控制台、文件、数据库);也可以控制每一条日志的输出格式,通过定义日志的输出级别,可以更灵活的控制日志的输出过程,方便项目的调试。

Log4j 组件

Log4j 主要由 Loggers(日志记录器)、Appenders(输出端)、Layout(日志格式化器)组成。

  • Loggers:控制日志的输出级别与日志是否输出
  • Appenders:指定日志的输出方式(控制台、文件)
  • Layout:控制台日志信息的输出格式

1. Loggers

Loggers:日志记录器,负责处理日志记录。实例的命名就是类的全限定名。Logger 的名字大小写敏感。其命名有继承机制。如:org.apache.commons 的 logger 会继承 org.apache 的 logger。

Log4j 中,有一个特殊的 logger,叫 root,它是所有的 logger 的根。root logger 可以通过 Logger.getRootLogger() 方法获取。

2. Appenders

Appenders 用来指定日志输出到哪个地方,可以同时指定日志的输出目的地。常用的目的地有以下几种:

  • ConsoleAppender:将日志输出到控制台
  • FileAppender:将日志输出到文件中
  • DailyRollingFileAppender:将日志输出到一个日志文件,并且每天输出到一个新的文件
  • RollingFileAppender:将日志输出到一个日志文件,并且指定文件的尺寸,当文件大小达到指定尺寸时,会自动把文件改名,同时,产生一个新的文件
  • JDBCAppender:将日志保存到数据库

3. Layouts

Layouts 用于控制日志输出内容的格式,让我们可以使用各种需要的格式输出日志。常用的 Layouts

  • HTML Layout:格式化日志输出为 HTML 表格形式
  • Simple Layout:简单的日志输出格式化。打印的日志格式为(info - message)
  • Pattern Layout:最强大的格式化器。可以根据自定义格式输出日志,如果没有指定转换格式,则使用默认的转换格式

2.2 快速入门

新建一个 SpringBoot 工程,引入 log4j 依赖:

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

入门案例:

public class Log4jTest {

    @Test
    public void testQuick() {
        Logger logger = Logger.getLogger(Log4jTest.class);
        logger.info("info");
    }

}

执行后,查看控制台:
在这里插入图片描述
由此可知,需要进行系统配置。一般用配置文件进行配置,这里暂时先用代码进行配置。

@Test
public void testQuick() {
    BasicConfigurator.configure();
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.info("info");
}

这样,日志信息就能正常输出。

2.3 日志级别

日志级别:

  • fatal:严重错误。一般会造成系统崩溃并终止运行
  • error:错误信息。不会影响系统运行
  • warn:警告信息。可能会发生问题
  • info:运行信息。数据连接、网络连接、IO操作等等
  • debug:调试信息。一般在开发中使用,记录程序变量参数传递信息等等
  • trace:追踪信息。记录程序所有的流程信息

Log4j 默认级别是 debug,只要日志级别高于 debug,都会输出。

2.4 使用配置文件

resources 下新建一个配置文件 log4j.properties

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = info,console
# 指定控制台日志输出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.SimpleLayout

在代码中使用:

@Test
public void testProperties() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.fatal("fatal");
    logger.error("error");
    logger.warn("warn");
    logger.info("info");
    logger.debug("debug");
    logger.trace("trace");
}

1. 自定义配置 Appender 的格式

log4j.properties 配置文件中,我们定义了日志输出级别与输出端,在输出端中分别配置日志的输出格式:

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = info,console
# 指定控制台日志输出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

log4j 采用类似 C 语言的 printf() 函数的打印格式格式化日志信息,具体的占位符及其含义如下:

%m=输出代码中指定的信息
%p=输出优先级
%n=换行符
%r=输出自应用启动到输出该 log 信息耗费的毫秒数
%c=输出打印语句所属的类的全限定名
%t=输出产生该日志的线程全名
%d=输出服务器当前时间。默认为 ISO8601。可指定格式:%d{yyyy年MM月dd日 HH:mm:ss}
%l=输出日志发生位置。包括:类名、线程名及在代码中的行数
%F=输出日志消息产生时所在的文件名称
%L=输出代码中的行号
%%=输出一个 % 字符

可以在 % 与字符之间加上修饰符来控制最小宽度,最大宽度和文本的对其方式。如:

%5c=输出类的全限定名,最小宽度是5,类名小于5,默认情况下右对齐
%-5c=输出类的全限定名,最小宽度是5,类名小于5,“-” 指定左对齐,会有空格
%.5c=输出类的全限定名,最大宽度是5,类名大于5,就会将左边多出的字符截掉;小于5,不会有空格
%20.30c%=类名小于20,补空格、右对齐;大于30,就会将左边多出的字符截掉

2. 自定义配置文件的 FileAppender

log4j.properties:将日志信息输出到文件 FileAppender

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = info,console,rollFile
# 指定控制台日志输出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

# 指定控制台日志输出的 appender
log4j.appender.file = org.apache.log4j.FileAppender
# 指定消息格式 layout
log4j.appender.file.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.file.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件的保存路径
log4j.appender.file.file = E:/temp/logs.log
# 指定日志文件的字符集
log4j.appender.file.encoding = UTF-8

log4j.properties:按照文件大小进行拆分

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = info,console,rollFile
# 指定控制台日志输出的 appender
log4j.appender.console = org.apache.log4j.ConsoleAppender
# 指定消息格式 layout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.console.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n

# 按照文件大小进行拆分的 appender 对象
log4j.appender.rollFile = org.apache.log4j.RollingFileAppender
# 指定消息格式 layout
log4j.appender.rollFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.rollFile.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件的保存路径
log4j.appender.rollFile.file = E:/temp/logs.log
# 指定日志文件的字符集
log4j.appender.rollFile.encoding = UTF-8
# 指定日志文件内容的大小
log4j.appender.rollFile.maxFileSize = 1MB
# 指定日志文件的数量
log4j.appender.rollFile.maxBackupIndex = 10
@Test
public void testPropertiesBySize() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    for (int i = 0; i < 10000; i++) {
        logger.fatal("fatal");
        logger.error("error");
        logger.warn("warn");
        logger.info("info");
        logger.debug("debug");
        logger.trace("trace");
    }
}

log4j.properties:按照时间大小进行拆分

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = info,dailyFile

# 按照时间大小进行拆分的 appender 对象
log4j.appender.dailyFile = org.apache.log4j.DailyRollingFileAppender
# 指定消息格式 layout
log4j.appender.dailyFile.layout = org.apache.log4j.PatternLayout
# 指定消息格式的内容
log4j.appender.dailyFile.layout.conversionPattern = [%p]%r  %l %d{yyyy-MM-dd HH:mm:ss} %m%n
# 指定日志文件的保存路径
log4j.appender.dailyFile.file = E:/temp/logs.log
# 指定日志文件的字符集
log4j.appender.dailyFile.encoding = UTF-8
# 指定日志文件拆分的规则
log4j.appender.dailyFile.datePattern = '.'yyyy-MM-dd-HH-mm-ss

3. 自定义 Logger

log4j.properties

# 指定 RootLogger 顶级父元素默认配置信息
# 指定日志级别=info,使用的 appender 是 console
log4j.rootLogger = trace,console

# 自定义 logger,也会继承RootLogger,所以也会输出到控制台
log4j.logger.com.zzc.sbexp.log.log4j = info,file
# apache 的logger,只有error级别及以上才会输出到控制台,并不会输出到文件
log4j.logger.org.apache = error

...
@Test
public void testMyLogger() {
    Logger logger = Logger.getLogger(Log4jTest.class);
    logger.fatal("fatal");
    logger.error("error");
    logger.warn("warn");
    logger.info("info");
    logger.debug("debug");
    logger.trace("trace");

    // apache 的 logger
    Logger logger1 = Logger.getLogger(Logger.class);
    logger1.fatal("fatal1");
    logger1.error("error1");
    logger1.warn("warn1");
    logger1.info("info1");
    logger1.debug("debug1");
    logger1.trace("trace1");
}

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值