本文最后更新于:2023-05-09T18:04:56+08:00
日志实现
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-core
、logback-classic
和logback-access
。其中logback-core
是其他两个模块的基础,而logback-classic
是log4j的一个改良版本,它完整实现了SLf4j
api,使得我们可以很方便地更换成其他日志系统。logback-access
则通过与Servlet容器集成,提供通过Http来访问日志的功能。
要想使用Logback,我们同样需要先引入下面的依赖。注意该依赖会自动引入其他两个依赖,分别是logback-core
和slf4j-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则不支持
参考文章
Introduction
to Java Logging - Baeldung
Java日志框架那些事