Java日志框架介绍与使用

日志实现

Log4j2

Log4j 是 Apache 的一个日志开源框架,提供多个分级(DEBUG/INFO/WARN/ERROR)记录级别,可以很好地将不同日志级别的日志分开记录,极大地方便了日志的查看。Log4j2也就是Log4j的2.x版本,也是目前官方推荐使用的版本。我们可以在官网Apache-log4j-2.x中看到更加详细的介绍

使用Log4j2,需要引入下面的依赖:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.20.0</version>
</dependency>

同时我们还需要一个配置文件,我们可以在其中指定日志系统的相关配置,具体位置为resources/log4j2.xml,下面是一个简单的配置文件例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="stdout"/>
</Root>
</Loggers>
</Configuration>

在上面的例子中,我们首先指定了一个Appender,其中主要用于指定日志记录的位置以及日志的格式,之后我们在Loggers标签中增加了标签使得我们的Appender生效,注意这里的level="info"指定了日志等级。接下来我们就可以在代码中记录日志了:

1
2
3
4
5
6
7
8
9
public class Log4J {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(Log4J.class);
logger.debug("Debug Message");
logger.info("Info Message");
logger.warn("Warning Message");
logger.error("Error Message");
}
}

可以发现在控制台中打印如下,由于指定了日志等级为info,因此只有INFO等级以上的日志被打印出来了。

1
2
3
2023-04-27 16:57:31 INFO Info Message
2023-04-27 16:57:31 WARN Warning Message
2023-04-27 16:57:31 ERROR Error Message

如果想要将日志打印到文件中,可以修改配置文件如下,修改主要就是增加了一个新的Appender,即这里的File标签,在其中指定日志输出位置以及日志格式。之后在Loggers中进行挂载增加即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
</Console>
<File name="file-out" fileName="log/logger-log4j2.log" append="true">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%nw</Pattern>
</PatternLayout>
</File>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="stdout"/>
<AppenderRef ref="file-out"/>
</Root>
</Loggers>
</Configuration>

Logback

Logback是Log4j的改进版本,它的开发者也是Log4j的开发人员,Logback的官网地址为:logback.qos.ch。Logback当前分为三个模块,logback-corelogback-classiclogback-access。其中logback-core是其他两个模块的基础,而logback-classic是log4j的一个改良版本,它完整实现了SLf4j api,使得我们可以很方便地更换成其他日志系统。logback-access则通过与Servlet容器集成,提供通过Http来访问日志的功能。

要想使用Logback,我们同样需要先引入下面的依赖。注意该依赖会自动引入其他两个依赖,分别是logback-coreslf4j-api

1
2
3
4
5
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.6</version>
</dependency>

类似地,我们也需要提供相关的配置文件,位置为resources/logback.xml,下面是一个简单的配置文件示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<configuration>
<appender name="std-out" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</Pattern>
</layout>
</appender>
<appender name="file-out" class="ch.qos.logback.core.FileAppender">
<file>log/logger-logback.log</file>
<append>true</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</pattern>
</encoder>
</appender>

<root level="INFO">
<appender-ref ref="std-out"/>
<appender-ref ref="file-out"/>
</root>
</configuration>

可以看到这里的概念和之前log4j中配置文件的概念是非常类似的。下面完成测试代码,需要注意的是这里使用的是slf4j的相关类,而没有直接使用logback相关的类。最终的运行效果与上面log4j中也是非常类似的。

1
2
3
4
5
6
7
8
9
10
11
12
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Logback {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Logback.class);
logger.debug("Debug Message");
logger.info("Info Message");
logger.warn("Warning Message");
logger.error("Error Message");
}
}

日志门面

SIf4J

在实际的项目应用当中,有时候可能会从一个日志框架切换到另一个日志框架。通常两个日志框架的使用方式是有所差异的,这就导致我们需要在代码上进行大量改动。所以为了避免切换日志组件时大量的代码改动,Slf4J出现了。Slf4J全称为Simple Logging Facade for Java,意为Java简单日志记录接口集。这是一个日志的接口规范,它向用户提供了统一的日志接口,而底层屏蔽了不同日志组件的差异。这样我们在实际编写代码的时候,只需要使用Slf4J提供给我们的接口即可,而不需要关注底层日志框架的区别。而当我们需要更换日志组件的时候,也只需要更换一个具体的日志组件Jar包就可以了。

下面的测试代码与上面Logback完全相同,因为Logback本身已经实现了Slf4J的接口。

1
2
3
4
5
6
7
8
9
10
11
12
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Logback {
public static void main(String[] args) {
Logger logger = LoggerFactory.getLogger(Logback.class);
logger.debug("Debug Message");
logger.info("Info Message");
logger.warn("Warning Message");
logger.error("Error Message");
}
}

如果需要使用其他的日志实现作为底层框架,则一般我们只需要修改引入的Maven依赖即可。通常我们需要引入slf4j-api以及具体日志实现的依赖,同时还需要引入一层连接器依赖,例如slf4j-log4j12,用于关联Slf4J和底层实际的日志组件。

最佳实践

目前主流的日志框架解决方案为Slf4J + Logback的组合,有如下几点原因:

  • LogBack自身实现了Slf4J的日志接口,而不需要Slf4J去做进一步的适配
  • LogBack是在Log4J的基础上优化而来的,其运行速率和效率都要高于Log4J
  • Slf4J + Logback支持占位符,方便日志代码的阅读,而Log4J则不支持

参考文章

  1. Introduction to Java Logging - Baeldung
  2. Java日志框架那些事

Java日志框架介绍与使用
http://example.com/2023/05/09/Java日志框架介绍与使用/
作者
EverNorif
发布于
2023年5月9日
许可协议