SpringBoot工具库:整合Logback、Log4j2
1、概念
- log4j是apache实现的一个开源日志组件
- logback同样是由log4j的作者设计完成的,拥有更好的特性,用来取代log4j的一个日志框架,是slf4j的原生实现
- Log4j2是log4j 1.x和logback的改进版,据说采用了一些新技术(无锁异步、等等),使得日志的吞吐量、性能比log4j 1.x提高10倍,并解决了一些死锁的bug,而且配置更加简单灵活
- slf4j:日志门面,服务于各种各样的日志系,是对所有日志框架制定的一种规范、标准、接口,并不是一个框架的具体的实现,因为接口并不能独立使用,需要和具体的日志框架实现配合使用(如log4j、logback),使用接口的好处是当项目需要更换日志框架的时候,只需要更换jar和配置,不需要更改相关java代码
2、使用条件
如果你开发的是类库或者嵌入式组件,那么就应该考虑采用SLF4J,因为不可能影响最终用户选择哪种日志系统。在另一方面,如果是一个简单或者独立的应用,确定只有一种日志系统,那么就没有使用SLF4J的必要。假设你打算将你使用log4j的产品卖给要求使用logback的用户时,面对成千上万的log4j调用的修改,相信这绝对不是一件轻松的事情。但是如果开始便使用SLF4J,那么这种转换将是非常轻松的事情。
说白了,slf4j和common-logging一个意思,就是简单的日志门面,方便我们在不动代码的前提下随意切换我们的日志框架。在部署的时候,选择不同的日志系统包,就可自动转换到不同的日志系统上。
比如:选择JDK自带的日志系统,则只需要将slf4j-api-1.5.10.jar和slf4j-jdk14-1.5.10.jar放置到classpath中即可,如果中途无法忍受JDK自带的日志系统了,想换成log4j的日志系统,仅需要用slf4j-log4j12-1.5.10.jar替换slf4j-jdk14-1.5.10.jar即可。(当然也需要log4j的jar及配置文件)。当然如果这个时候觉得log4j的性能不是太好,出于性能考虑想换成logback的日志系统的话,也只是需要将logback的core包和classic包替换原来的log4j包就OK(当然也需要logback的配置文件)。
结合各日志实现包使用时提供的jar包情况为:
- SLF4J和logback结合使用时需要提供的jar:slf4j-api.jar,logback-classic.jar,logback-core.jar
- SLF4J和log4j结合使用时需要提供的jar:slf4j-api.jar,slf4j-log412.jar,log4j.jar
- SLF4J和JDK中java.util.logging结合使用时需要提供的jar:slf4j-api.jar,slf4j-jdk14.jar
- SLF4J和simple(SLF4J本身提供的一个接口的简单实现)结合使用时需要提供的jar:slf4j-api.jar,slf4j-simple.jar
注意,以上slf4j和各日志实现包结合使用时最好只使用一种结合,不然的话会提示重复绑定日志,并且会导致日志无法输出。
3、依赖pom.xml
log4j2默认会在classpath目录下寻找log4j2.xml、log4j.json、log4j.jsn等名称的文件,如果都没有找到,则会按默认配置输出,也就是输出到控制台,也可以对配置文件自定义位置
国外的服务器下载速度感人,一般都是用公司内部地址或切换到国内。 修改maven安装目录下中的conf文件夹下的setting.xml
文件内容,在<mirrors>节点下新增
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
4、SLF4J+log4j
Logback默认配置的步骤:
1). 尝试在 classpath下查找文件logback-test.xml;
2). 如果文件不存在,则查找文件logback.xml;
3). 如果两个文件都不存在,logback用BasicConfigurator自动对自己进行配置,这会导致记录输出到控制台。
4.1.spring项目
本项目是基于spring项目集成logback日志
pom.xml
<!-- slf4j依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
<!-- slf4j自带的简单日志 -->
<!-- log4j依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
4.2.Springboot项目
springboot项目,直接引入spring-boot-starter-web
依赖即可,因为spring-boot-starter-web
包含了spring-boot-starter
。
而spring-boot-starter
包含了spring-boot-starter-logging
,所以我们只需要引入 web 组件即可。
1)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2)添加配置在application.yml
# 日志配置
logging:
# 指定配置文件的路径
config: classpath:logback-spring.xml
level:
# root表示整个项目,默认级别为info
root: info
3)logback-spring.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!--spirng boot 默认使用logback,默认会读取resources文件夹下的名为logback.xml的文件 -->
<configuration debug="true">
<!-- 指定日志文件路径(与当前程序jar包同一目录下) -->
<property name="LOG_HOME" value="logs/TokenUtils"/>
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint}%clr(%-40.40logger{39}:%4line){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n</pattern>
</encoder>
</appender>
<!--按照每天生成日志文件 -->
<appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/debug/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/debug/debug.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!-- 日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/order/error/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/error/error.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>15</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_HOME}/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/info/info.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志输出级别: application.yml 中的配置会覆盖 logback-spring.xml 中的配置-->
<!-- 打印INFO级别日志及以上级别日志 -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG" />
<appender-ref ref="ERROR" />
<appender-ref ref="INFO" />
</root>
</configuration>
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
小技巧: 在根pom里面设置统一存放路径,统一管理方便维护
<properties>
<log-path>/Users/xx</log-path>
</properties>
1. 其他模块加日志输出,直接copy本文件放在resources 目录即可
2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块
-->
<configuration debug="true">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="log.path" value="logs/${project.artifactId}"/>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg %n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="DEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/debug/debug.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/insurrance/debug/debug.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error/error.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/insurrance/error/error.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>15</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info/info.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/insurrance/info/info.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="WARN" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/warn/warn.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/insurrance/warn/warn.log.%d{yyyy-MM-dd}_%i</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
<TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<MaxFileSize>1024MB</MaxFileSize>
</TimeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="DEBUG" />
<appender-ref ref="ERROR" />
<appender-ref ref="INFO" />
<appender-ref ref="WARN" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
${project.artifactId}读取的是项目下pom.xml文件中项目信息,通过变量方式,避免硬编码
5、SLF4J+Log4j
SpringBoot整合Log4j2步骤:
1)删除spring-boot-starter-parent默认使用spring-boot-starter-logging依赖
2)在pom.xml中增加spring-boot-starter-log4j2依赖
3)创建log4j2.xml文件即可
4)执行,指定目录会生成相应的log文件
1)加入依赖
springboot默认使用的是logback
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions><!-- 去掉springboot默认配置 -->
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <!-- 引入log4j2依赖 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
2)log4j2.xml
在src.java.main.resources目录下创建log4j2.xml文件 log4j2.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="fatal">
<Properties>
<!--配置日志文件夹的名称和生成路径,可以是D:\xx-logs,如果直接写 xx-logs 就是项目的根目录 -->
<Property name="baseDir" value="dongrong-logs"/>
</Properties>
<!--定义appender-->
<appenders>
<!--控制台的输出配置-->
<console name="Console" target="SYSTEM_OUT">
<!-- 设置控制台只输出INFO及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<!--输出日志的格式-->
<PatternLayout pattern="${log_pattern}"/>
</console>
<!-- 所有的日志信息会打印到此文件中,append=false每次启动程序会自动清空 -->
<!-- <File name="all" fileName="${file_path}/all.log" append="true">
<PatternLayout pattern="${log_pattern}"/>
</File>-->
<!--
该RollingFile存储INFO级别的日志,
默认存储到 fileName 文件中
超过SizeBasedTriggeringPolicy的设定值,则存储到 filePattern 文件中
-->
<RollingFile name="RollingFileInfo" fileName="${file_path}/info.log" filePattern="${file_path}/${backup_folder}/info${backup_file_suffix}">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- 写入日志文件的模板 -->
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,超过该数量,会滚动删除前面的记录 -->
<DefaultRolloverStrategy max="5">
<Delete basePath="" maxDepth="">
<IfFileName glob="*.log" />
<IfLastModified age="*1d" />
</Delete>
</DefaultRolloverStrategy>
<!--多长时间滚动一次-->
<TimeBasedTriggeringPolicy interval="2 hour" />
<!-- 一个日志文件的最大大小 -->
<SizeBasedTriggeringPolicy size="${file_max_size}"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="${file_path}/warn.log" filePattern="${file_path}/${backup_folder}/warn${backup_file_suffix}">
<ThresholdFilter level="WARN" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${file_max_size}"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileError" fileName="${file_path}/error.log" filePattern="${file_path}/${backup_folder}/error${backup_file_suffix}">
<ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${log_pattern}"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="${file_max_size}"/>
</Policies>
</RollingFile>
</appenders>
<!-- 只有定义了logger并使用appender-ref,appender才会生效 -->
<loggers>
<!--过滤掉spring和hibernate的一些无用的debug信息-->
<logger name="org.springframework" level="INFO"/>
<logger name="org.mybatis" level="INFO">
<!-- 添加如下设置,控制台会再打印一次 -->
<AppenderRef ref="Console"/>
</logger>
<root level="INFO">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</Configuration>
3)yml中设置配置文件路径
logging:
config: classpath:log4j2.xml
配置参数详解
1)输出源
-
CONSOLE(输出到控制台)
-
FILE(输出到文件
6、Java测试
6.1、使用方式
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Slf4jTest
{
private static Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
@Test
public void test()
{
logger.debug("debug()方法,看下这里logger的实例是:{}", logger.getClass());
logger.info("info()方法,看下这里logger的实例是:{}", logger.getClass());
logger.error("error()方法,看下这里logger的实例是:{}", logger.getClass());
}
}
6.2、验证
使用logback来输出日志:去掉pom文件中多余的日志框架的依赖,添加logback-core和logback-classic的依赖到pom中,运行上面的测试,控制台输出如下
[main] INFO com.ykx.insurance.Slf4jTest - info()方法:logger的实例:class ch.qos.logback.classic.Logger
[main] ERROR com.ykx.insurance.Slf4jTest - error()方法:logger的实例:class ch.qos.logback.classic.Logger
使用slf4j输出日志:slf4j也给我们提供了一个简单的simple日志框架。注释掉别的pom依赖,只打开slf4j-simple的依赖。运行上面的测试控制台输出如下:
[main] INFO org.linkinpark.commons.slf4j.Slf4jTest - info()方法:logger的实例是:class org.slf4j.impl.SimpleLogger
[main] ERROR org.linkinpark.commons.slf4j.Slf4jTest - error()方法:logger的实例是:class org.slf4j.impl.SimpleLogger
小结
通过上面这个比较详细的例子,我们看到了,我们使用slf4j来统一管理的我们的代码,我们不停的切换了多种日志框架来作为我们的日志输出,但是我们的业务代码,Java类中的那些日志输出代码一点都不用去改,这也真是slf4j最迷人的地方。它完美的整合了自己的一个简单日志,JDK自带的日志,log4j,logback,common-logging。只不顾我们在转换日志输出的时候,可能会用到一些中间的桥接jar包。
当然,我仔细有看过这些桥接类的maven依赖,比如:
slf4j-log4j12:它本身就会依赖slf4j-api和log4j,maven依赖的jar包是可以传递的,所以也可以不用人工的去添加这些jar包的。
slf4j-jcl:它本身就会依赖slf4j-api和common-logging,maven依赖的jar包是可以传递的,所以也可以不用人工的去添加这些jar包的。
slf4j-jdk14:它本身就会依赖slf4j-api,maven依赖的jar包是可以传递的,所以也可以不用人工的去添加这些jar包的。
SLF4J还有一个比较直接的吸引人的地方就是Java代码中输出日志的Java写法,性能很好,如果配合logback使用据说是log4j性能的10倍,特别是有字符串连接的时候。
在使用Commons Logging时,我们经常会看到以下方法的写法:
例如:
if (logger.isDebugEnabled())
{
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
存在isDebugEnabled()的判断逻辑是为了在避免多余的字符串拼接,即如果不存在isDebugEnabled()判断,即使当前日志级别为ERROR时,在遇到logger.info()调用时,它还会先拼接日志消息的字符串,然后进入该方法内,才发现这个日志语句不用打印。而这种多余的拼接不仅浪费了多余的CPU操作,而且会增加GC的负担。SLF4J则提供以下的方式来解决这个问题:
logger.info("Loading XML bean definitions from {}", encodedResource.getResource());
总结如下:
1、slf4j是java的一个日志门面,实现了日志框架一些通用的api,log4j和logback是具体的日志框架。
2、他们可以单独的使用,也可以绑定slf4j一起使用。