1. 概述
简单Java日志门面(简称SLF4J)作为不同日志框架(如java.util.logging, logback, Log4j)的外观模式。它提供了一个通用的API,使得日志独立于实际实现,从而支持多种框架共存、迁移以及提供标准化的接口和一些“语法糖”。
本教程将讨论如何与Log4j、Logback、Log4j 2和Jakarta Commons Logging集成SLF4J所需的依赖和配置。
有关这些实现的更多信息,请参阅我们的文章:Java日志入门。
2. Log4j 2 配置
要使用SLF4J与Log4j 2集成,我们需要在pom.xml
中添加以下库:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.7</version>
</dependency>
最新版本可以在以下链接找到:log4j-api,log4j-core,log4j-slf4j-impl。
实际的日志配置遵循Log4j 2的原生配置。
让我们看看如何创建Logger
实例:
public class Slf4jExample {
private static Logger logger = LoggerFactory.getLogger(Slf4jExample.class);
public static void main(String[] args) {
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
}
}
请注意,Logger
和LoggerFactory
来自org.slf4j
包。
有关此配置示例项目的运行,请查看这里。
3. Logback 配置
由于Logback本身已经使用了SLF4J,所以我们不需要将SLF4J添加到类路径中以使用它。Logback是SLF4J的参考实现。
因此,我们只需要包含Logback库:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.6</version>
</dependency>
最新版本可以在logback-classic找到。
配置是Logback特有的,但与SLF4J无缝协作。有了适当的依赖和配置,我们可以使用之前章节中的相同代码来处理日志。
4. Log4j 配置
在前面的章节中,我们探讨了SLF4J“置于”特定日志实现之上的用法,它完全隐藏了底层框架。有时,由于第三方要求,我们无法替换现有的日志解决方案,但这并不限制项目只使用已有的框架。
我们可以配置SLF4J作为桥接器,将对现有框架的调用重定向到它。
让我们添加必要的依赖以建立Log4j的桥接:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
有了这个依赖(请检查log4j-over-slf4j的最新版本),所有对Log4j的调用都将被重定向到SLF4J。
请参阅官方文档了解如何桥接现有框架的更多内容。
如同其他框架一样,Log4j也可以作为底层实现。
让我们添加必要的依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
这些最新的版本可以在slf4j-log4j12和log4j中找到。配置为此方式的示例项目可在这里找到。
5. JCL桥接器配置
在前面的章节中,我们展示了如何使用相同的代码库支持不同实现的日志。这是SLF4J的主要承诺和优势,也是Jakarta Commons Logging(或Apache Commons Logging,简称JCL)背后的目标。
JCL旨在作为一个类似于SLF4J的框架。主要区别在于,JCL在运行时通过类加载系统动态确定底层实现。在存在自定义类加载器的情况下,这种方法可能存在问题。
SLF4J在编译时解决绑定,被认为是更简单但功能强大的。
幸运的是,两个框架可以在桥接模式下协同工作:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.30</version>
</dependency>
最新的依赖版本可以在jcl-over-slf4j找到。
与其他情况一样,相同的代码库将运行良好。
6. SLF4J 的额外功能
SLF4J提供了额外的功能,可以使日志更高效,代码更易读。
例如,SLF4J提供了非常有用的参数工作接口:
String variable = "Hello John";
logger.debug("Printing variable value: {}", variable);
以下是Log4j做同样事情的代码:
String variable = "Hello John";
logger.debug("Printing variable value: " + variable);
如我们所见,Log4j会在任何情况下将String
拼接起来。在高负载应用中,这可能导致性能问题。相反,SLF4J只有在debug
级别启用时才会拼接String
。
要在Log4j中实现相同功能,我们需要添加一个额外的if
块,检查debug
级别是否启用:
String variable = "Hello John";
if (logger.isDebugEnabled()) {
logger.debug("Printing variable value: " + variable);
}
SLF4J标准化了日志级别,这些级别在特定实现中有所不同。它移除了Log4j引入的FATAL
级别,理由是在日志框架中,我们不应该决定何时终止应用程序。
使用的日志级别是ERROR
、WARN
、INFO
、DEBUG
和TRACE
。有关更多使用信息,请参阅我们的文章:Java日志入门。
7. 总结
SLF4J有助于在不发出声音的情况下在日志框架之间切换。它简单而灵活,可以提高可读性和性能。
如往常一样,代码可在GitHub上找到。此外,我们还引用了一个专注于不同文章的项目,其中包含了讨论过的日志配置,可在这里找到。