一、总体介绍
目前java日志框架有以下几种:
日志框架 | 描述 | 相关jar |
Jdk logging | jdk 自带的 | slf4j-jdk14、jul-to-slf4j |
log4j | Apache 的一个开放源代码项目 | log4j、slf4j-log4j12、log4j-over-slf4j |
log4j2 | Log4j的加强版 | log4j-api、log4j-core、log4j-slf4j-impl |
logback | Logback 是由 log4j 创始人设计的又一个开源日记组件 | logback-core、logback-classic |
Jcl | commons-logging是Apache commons类库中的一员、能够选择使用Log4j还是JDK Logging,但是他不依赖Log4j,JDK Logging的API | commons-logging、slf4j-jcl 、jcl-over-slf4j |
jcl:
从jcl源码中可以看出,jcl有4个四个选择:jdk13,jdk14,log4j,simpleLog,jcl加载时按照顺序log4j>jdk13>jdk14> simpleLog依次加载,如果查找到log4j包则使用log4j,如果没有依次类推。
我们可以写个例子来验证下这点:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
package javaLog;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class LogTest {
static Log jcl = LogFactory.getLog(LogTest.class);
public static void main(String[] args) {
jcl.info("jcl---------------hello---------------");
}
}
运行结果可以看出采用的是jdk loggin,这正印证了我们所说的找不到log4j后接着就是找jdk:
如果我们追加log4j的jar包进去:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
slf4j:
Slf4j它是通过中间集合jar包去桥接他们的实现。
二、相关运用
引出问题:如果项目中旧模块使用的是log4j来打印日志的话,而新模块想用logback来统一打印日志的话,那么这时该怎么办呢?
难不成让他们输出两个日志文件呀,那样太乱了,那也不能去改旧模块代码吧,这太耗时了,最佳方案可以这么做:去掉log4j包引入log4j-over-slf4j包(这个包使之前代码使用log4j不会因为找不到而报错)和slf4j-api,以及logback-core和logback-classic(将slf4j桥接到logback),意思是让log4j交给slf4j,然后让slf4j桥接到logback,如下图所示:
所需要jar包:
log4j-over-slf4j | 实现log4j1切换到slf4j |
slf4j-api | slf4j所需jar |
logback-core | logback核心包 |
logback-classic | slf4j与logback集成包 |
代码测试:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency> -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.13</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.3</version>
</dependency>
package javaLog;
import org.apache.log4j.Logger;
public class LogTest {
static Logger log4j = Logger.getLogger(LogTest.class);
static org.slf4j.Logger logback = org.slf4j.LoggerFactory.getLogger(LogTest.class);
public static void main(String[] args) {
log4j.info("log4j---------------hello---------------");
logback.info("logback---------------hello---------------");
}
}
打印结果可以看出,日志输出一致:
同理如果实现从jdk loggin切换到log4j呢,和上面差不多
所需jar包
jul-to-slf4j | 实现jdk-logging切换到slf4j |
slf4j-api | slf4j所需jar |
log4j | log4j所需包 |
slf4j-log4j12 | slf4j与log4j集成包 |
代码测试:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cwh.javaLog</groupId>
<artifactId>javaLog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build/>
</project>
package javaLog;
import java.util.logging.Logger;
import org.slf4j.bridge.SLF4JBridgeHandler;
public class LogTest {
static{
SLF4JBridgeHandler.install();
}
static Logger jul = Logger.getLogger(LogTest.class.getName());
static org.slf4j.Logger log4j = org.slf4j.LoggerFactory.getLogger(LogTest.class);
public static void main(String[] args) {
jul.info("jul---------------hello---------------");
log4j.info("log4j---------------hello---------------");
}
}
打印结果可以看出,日志输出一致:
三、jcl的log4j实现切换为log4j2
原理如下图:
说明:将jcl适配给slf4j,然后slf4j桥接到log4j2
所需jar包:
jcl-over-slf4j | jcl适配slf4j集成包 |
slf4j-api | slf4j所需 |
log4j-api | log4j2接口 |
log4j-core | log4j核心实现 |
log4j-slf4j-impl | log4j与slf4j集成包 |
测试代码:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cwh.javaLog</groupId>
<artifactId>javaLog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<!-- <dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency> -->
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
<build/>
</project>
package javaLog;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
static Log jcl = LogFactory.getLog(LogTest.class);
static Logger log4j2 = LoggerFactory.getLogger(LogTest.class);
public static void main(String[] args) {
jcl.info("jcl---------------hello---------------");
log4j2.info("log4j2---------------hello---------------");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy/MM/dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</Loggers>
</Configuration>
运行结果可以看出日志打印以及统一为log4j2:
以上纯属个人绵薄认识,如有不对地方望指正