1. 概述
日志是理解和调试程序运行时行为的利器。它能捕获并持久化关键数据,方便随时进行分析。本文将深入探讨最流行的Java日志框架——Log4j 2和Logback,以及它们的鼻祖Log4j,并简要介绍SLF4J这个为不同日志框架提供统一接口的门面库。
2. 启用日志
所有日志框架都遵循三个核心概念:Logger(日志记录器)、Appender(输出端)和Layout(布局)。在项目中启用日志通常分三步走:
- 添加所需依赖
- 配置框架
- 在代码中插入日志语句
接下来我们分别针对每个框架详解这些步骤。
3. Log4j 2
Log4j 2是Log4j的升级版,最吸引人的改进是支持异步日志。需要添加以下依赖:
<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>
关键点说明:
name
属性可自定义(如用"console"替代"stdout")PatternLayout
控制日志格式:%d
:日期格式%p
:日志级别%m
:日志消息%n
:换行符
启用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
:消息格式(同前)
启用文件日志:
<Root level="INFO">
<AppenderRef ref="stdout" />
<AppenderRef ref="fout"/>
</Root>
3.3 异步日志
启用异步日志需添加LMAX disruptor依赖(无锁线程通信库):
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.4</version>
</dependency>
两种异步配置方式:
- 使用
<AsyncRoot>
替代<Root>
:<AsyncRoot level="DEBUG"> <AppenderRef ref="stdout" /> <AppenderRef ref="fout"/> </AsyncRoot>
- 设置系统属性:
System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
性能优化细节可参考官方指南。
3.4 使用示例
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");
}
}
输出结果:
2016-06-16 17:02:13 INFO Info log message
2016-06-16 17:02:13 ERROR Error log message
日志级别控制:当Root level设为ERROR时:
<level value="ERROR" />
输出将变为:
2016-06-16 17:02:13 ERROR Error log message
异常记录技巧:
try {
// 可能抛出异常的代码
} catch (Exception e) {
logger.error("Error log message", throwable); // 关键:第二个参数传异常对象
}
3.5 包级别配置
假设需要为com.baeldung.log4j2
包启用TRACE级别日志:
logger.trace("Trace log message"); // 仅在特定包生效
配置方法:在<Root>
前添加:
<Logger name="com.baeldung.log4j2" level="debug">
<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原作者打造的升级版,功能更丰富(官方优势说明)。添加依赖:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
此依赖会自动引入
logback-core
和slf4j-api
4.1 配置示例
<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>
4.2 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");
}
}
输出结果与Log4j 2示例完全一致
5. Log4j(经典版)
虽然Log4j 1.x已过时,但作为现代日志框架的基石仍值得了解。配置细节与Log4j 2相似。
5.1 配置
添加依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
控制台输出配置示例:
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
<log4j:configuration debug="false">
<!-- 控制台Appender -->
<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>
debug="false"
表示不输出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的核心用法。关键要点:
- Log4j 2:异步日志性能优异,配置灵活
- Logback:SLF4J原生支持,功能丰富
- Log4j:历史版本,新项目不推荐
踩坑提示:
- 日志配置文件路径错误会导致静默失败
- 异步日志需注意Disruptor版本兼容性
- 包级别配置时注意大小写敏感
完整代码示例见GitHub仓库。