baeldung 2024-05-11
1. 概述
日志是理解和调试程序运行时行为的有力工具。日志能够捕获并持久化重要数据,使其在任意时间点都可用于分析。
本文将讨论最流行的 Java 日志框架——Log4j 2 和 Logback,以及它们的前身 Log4j,并简要介绍 SLF4J(一个为不同日志框架提供统一接口的日志门面)。
2. 启用日志
本文讨论的所有日志框架都基于 Logger(记录器)、Appender(输出目标) 和 Layout(格式布局) 的概念。在项目中启用日志通常包括以下三个通用步骤:
- 添加所需依赖库
- 配置日志
- 在代码中插入日志语句
接下来的章节将分别介绍每个框架的具体实现方式。
3. Log4j 2
Log4j 2 是 Log4j 日志框架的新一代改进版本。其最引人注目的改进是支持异步日志记录。使用 Log4j 2 需要添加以下依赖库:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.6.1</version>
</dependency>
3.1 配置
Log4j 2 的配置基于主配置文件 log4j2.xml。首先需要配置的是 Appender(输出目标),它决定了日志消息的输出位置,例如控制台、文件、Socket 等。
Log4j 2 提供了多种 Appender,具体信息可参考 官方文档。
下面是一个简单的配置示例:
<Configuration status="debug" name="baeldung" packages="">
<Appenders>
<Console name="stdout" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %p %m%n"/>
</Console>
</Appenders>
</Configuration>
- 每个 Appender 可以指定名称,例如将
name="stdout"改为name="console"。 <PatternLayout>元素定义了日志消息的格式:%d:日期格式%p:日志级别%m:日志消息内容%n:换行符
更多格式说明请参阅 Log4j 2 官方文档。
最后,要启用一个或多个 Appender,需将其添加到 <Loggers> 节点中:
<Loggers>
<Root level="error">
<AppenderRef ref="stdout"/>
</Root>
</Loggers>
3.2 文件日志
有时需要将日志写入文件,为此可在配置中添加一个 File 类型的 Appender:
<Appenders>
<File name="fout" fileName="baeldung.log" append="true">
<PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</Pattern>
</PatternLayout>
</File>
</Appenders>
File Appender 的常用参数包括:
fileName:日志文件名append:默认为true,表示追加写入而非覆盖PatternLayout:与控制台日志相同的格式配置
要启用该文件 Appender,需将其加入 <Root> 节点:
<Root level="INFO">
<AppenderRef ref="stdout" />
<AppenderRef ref="fout"/>
</Root>
3.3 异步日志
若希望启用 Log4j 2 的异步日志功能,需在 pom.xml 中添加 LMAX Disruptor 库(一种无锁线程间通信库):
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
最新版本的 Disruptor 可在 Maven Central 查询。
启用异步日志有两种方式:
- 在配置中使用
<AsyncRoot>替代<Root>:
<AsyncRoot level="DEBUG">
<AppenderRef ref="stdout" />
<AppenderRef ref="fout"/>
</AsyncRoot>
- 或通过设置系统属性:
-DLog4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
更多异步日志配置和性能对比可参考 Log4j 2 官方文档。
3.4 使用示例
以下是一个使用 Log4j 2 的简单示例:
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
public class Log4jExample {
private static Logger logger = LogManager.getLogger(Log4jExample.class);
public static void main(String[] args) {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
运行后,日志将同时输出到控制台和 baeldung.log 文件中:
2016-06-16 17:02:13 INFO Info log message
2016-06-16 17:02:13 ERROR Error log message
如果将根日志级别设为 ERROR:
<Root level="ERROR">
<AppenderRef ref="stdout" />
</Root>
则输出仅包含错误日志:
2016-06-16 17:02:13 ERROR Error log message
此外,logger.error() 还可用于记录异常:
try {
// 可能抛出异常的代码
} catch (Exception e) {
logger.error("Error log message", e);
}
3.5 包级别配置
假设你希望对特定包(如 com.baeldung.log4j2)启用 TRACE 级别日志,而其他包仍保持 INFO 级别。
由于 TRACE 级别低于全局 INFO,需在 <Root> 之前添加专用 <Logger> 配置:
<Logger name="com.baeldung.log4j2" level="trace">
<AppenderRef ref="stdout"/>
</Logger>
此时,该包下的日志输出将包含所有级别:
2016-06-16 17:02:13 TRACE Trace log message
2016-06-16 17:02:13 DEBUG Debug log message
2016-06-16 17:02:13 INFO Info log message
2016-06-16 17:02:13 ERROR Error log message
4. Logback
Logback 是由 Log4j 原作者开发的新一代日志框架,旨在改进 Log4j。它比 Log4j 功能更丰富,许多特性后来也被引入 Log4j 2。
要使用 Logback,只需添加以下依赖:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
该依赖会自动引入
logback-core和slf4j-api。最新版本可在 Maven Central 查询。
4.1 配置示例
Logback 的配置文件通常为 logback.xml,示例如下:
<configuration>
<!-- 控制台输出 -->
<appender name="stdout" 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="fout" class="ch.qos.logback.core.FileAppender">
<file>baeldung.log</file>
<append>false</append>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %m%n</pattern>
</encoder>
</appender>
<!-- 为特定包设置日志级别 -->
<logger name="com.baeldung.log4j" level="TRACE"/>
<root level="INFO">
<appender-ref ref="stdout" />
<appender-ref ref="fout" />
</root>
</configuration>
注意:Logback 使用 SLF4J 作为其原生 API。
4.2 SLF4J
SLF4J(Simple Logging Facade for Java)为各种 Java 日志框架提供了统一的接口抽象。它作为一个“门面”,允许开发者通过标准化 API 访问底层日志实现。
Logback 原生支持 SLF4J。以下是使用 Logback + SLF4J 的代码示例:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Log4jExample {
private static Logger logger = LoggerFactory.getLogger(Log4jExample.class);
public static void main(String[] args) {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
输出结果与前述示例一致。
5. Log4j(经典版)
Log4j 是早期广泛使用的日志框架,现已过时,但因其奠定了现代日志框架的基础,仍值得了解。
其配置方式与 Log4j 2 类似。
5.1 配置
首先添加依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
最新(也是最终)版本可在 Maven Central 查询。
以下是一个仅包含控制台输出的简单配置:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
<appender name="stdout" class="org.apache.log4j.ConsoleAppender">
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %p %m%n" />
</layout>
</appender>
<root>
<level value="INFO" />
<appender-ref ref="stdout" />
</root>
</log4j:configuration>
<log4j:configuration debug="false">中的debug属性控制是否输出 Log4j 自身的调试信息。
5.2 使用示例
配置完成后,即可在代码中使用:
import org.apache.log4j.Logger;
public class Log4jExample {
private static Logger logger = Logger.getLogger(Log4jExample.class);
public static void main(String[] args) {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
6. 结论
本文展示了如何使用 Log4j、Log4j 2 和 Logback 三种主流 Java 日志框架,并提供了各自的简单配置示例。通过合理配置日志级别、输出目标和格式,开发者可以高效地监控和调试应用程序。