上一篇(日志那些事之一—java日志框架分类)主要介绍了Java中常用的日志框架以及不同的日志级别,本篇将针对上一篇提到的几种日志框架做详细地介绍,并说明不同的日志框架在实际的代码中如何使用,具体的日志demo,如下:
https://github.com/OnlyIsssilence/loggerDemo
如果是在一个新的项目中建议使用Slf4j与Logback组合,这样有如下的几个优点:
if(log.isDebugEnabled()){
log.debug("User name: " +
user.getName() + " buy goods id :" + good.getId());
}
Slf4j阵营,你只需这么做: Slf4j与其他各种日志组件的“拼接”方案,早已经被有了开源的api包,如表2所示:
拼接之后的jar包名称 | 说明 |
---|---|
Slf4j-logj12-1.7.13.jar | Log4j1.2版本的桥接器,需要将log4j.jar加入到classpath中 |
Slf4j-jdk14-1.7.13.jar | Java.util.logging的桥接器,JDK原生日志框架 |
Slf4j-jcl-1.7.13.jar | Jakarta commons logging的桥接器,这个桥接器将SLF4J所有日志委派给JCL |
Logback-classic-1.0.13.jar(需要logback-core-1.0.13.jar) | Slf4j的原生实现,logback直接实现了slf4j的接口,因此使用slf4j与logback的结合使用也意味着更小的内存与计算开销 |
slf4j-simple-1.7.13.jar | 一个简单实现的桥接器,该实现输出所有事件到system.err,只有info以及高于该级别的消息被打印 |
Slf4j-nop-1.7.13 | NOP桥接器,丢弃一切日志 |
在实际环境中我们经常会遇到不同的组件使用的日志框架不同的情况,例如Spring Framework使用的是日志组件是Commons logging,XSocket依赖的则是Java Util Logging。当我们在同一项目中使用不同的组件时应该如果解决不同组件依赖的日志组件不一致的情况呢?现在我们需要统一日志方案,统一使用SLF4J,把他们的日志输出重定向到SLF4J,然后 SLF4J 又会根据绑定器把日志交给具体的日志实现工具。Slf4j带有几个桥接模块,可以重定向log4j,JCL和java.util.logging中的API到Slf4j。
重定向包名 | 作用 |
---|---|
Log4j-over-slf4j-version.jar | 将log4j重定向到slf4j将commons logging里的simple logger重定向到slf4j |
Jul-to-slf4j-version.jar | 将java util logging重定向到slf4j |
在使用slf4j桥接时要注意避免形成死循环,在项目依赖的jar包中不要存在以下情况。如下表4所示:
多个日志jar包形成死循环的条件 | 产生的原因 |
---|---|
Log4j-over-slf4j.jar和slf4j-log4j12.jar同时存在 | 由于slf4j-log4j12.jar的存在会将所有的日志调用委托给log4j,但由于Log4j-over-slf4j.jar的存在,会将所有对log4j.api的调用委托给相应等值的slf4j,所有它们同时存在会出现死循环 |
Jul-to-slf4j.jar和slf4j-jdk14.jar同时存在 | 由于slf4j-jdk14.jar的存在会将所有的日志调用委托给jdk的log,但由于Jul-to-slf4j.jar的存在,会将所有对jul.api的调用委托给相应等值的slf4j,所有它们同时存在会出现死循环 |
Pom包与使用的包类文件:无依赖,有JDK即可
sun本身自带的日志工具
import java.util.logging.LogManager;
import java.util.logging.Logger;
public final static Logger logger = LogManager.getLogManager().getLogger("");
public static void main( String[] args )
{
System.out.println( "Hello World!" );
logger.info("日志测试!");
}
输出结果:
Hello World!
三月 08, 2018 12:07:42 上午 java.util.logging.LogManager$RootLogger log
信息: 日志测试!
Pom包与使用的包类文件:
/**
* apach下的log4j日志工具
* import org.apache.log4j.LogManager;
* import org.apache.log4j.Logger;
*
*
* log4j
* log4j
* 1.2.17
*
*/
public final static Logger logger = LogManager.getLogger(App.class.getName());
输出结果:
Hello World!
[2018-03-08 00:09:49 INFO] com.onlyisssilence.muya.App:78 - 日志测试!
注意:
使用log4j与log4j2日志框架时,由于它们需要读取对应的日志”模型”——appender、logger,通俗地说即是日志的输出格式,日志输出到哪的参数,此时需要分别在工程的resource位置(也可以是其他的位置,但是一定要通过代码的方式显示地告诉编译器日志配置文件的位置)上添加对应格式的配置文件,log4j的配置文件如下所示:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8"/>
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="[%d{yyyy-MM-dd HH:mm:ss\} %p] %c:%L - %m%n"/>
layout>
appender>
<root>
<priority value="debug"/>
<appender-ref ref="console"/>
root>
log4j:configuration>
Pom包与使用的包类文件:
为了偷懒直接使用了如下图中的pom依赖
这里简单分析一下这个依赖,如上图所示,pom工程实际上只依赖了一个spring-boot-starter-log4j2的包,然后这个包有分别直接依赖了后面的5个,上图中红色圈圈中的三个包是使用log4j2日志框架的核心包,如果在工程中不导入spring-boot-starter-log4j2包,而直接导入红圈中三个包也是可行的,如下所示:
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.0.1version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.0.1version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-slf4j-implartifactId>
<version>2.0.1version>
dependency>
同log4j一样,所需要加入的配置文件:
<Configuration>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="[%-5p] %d %c - %m%n"/>
Console>
Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
Root>
Loggers>
Configuration>
Pom包与使用的包类文件:
/**
* Logback 基于slf4j
* import org.slf4j.Logger;
* import org.slf4j.LoggerFactory;
*
*
* ch.qos.logback
* logback-classic
* 1.2.3
*
*/
public final static Logger logger = LoggerFactory.getLogger(App.class.getName());
输出结果
Hello World!
00:23:45.812 [main] INFO com.onlyisssilence.muya.App - 日志测试!
从结果上来看可以发现log4j2与logback日志一样,他们都是实现的是slf4j的日志接口
Pom包与使用的包类文件:
/**
* common logging 包装了sun自己的log工具和apach下的log4j工具
* import org.apache.commons.logging.Log;
* import org.apache.commons.logging.LogFactory;
*
*
* commons-logging
* commons-logging
* 1.2
*
*/
public final static Log logger = LogFactory.getLog(App.class.getName());
输出结果
Hello World!
三月 08, 2018 12:29:32 上午 com.onlyisssilence.muya.App main
信息: 日志测试!
注意:如第二节中提到的,commons logging日志框架接口,其内部其实已经有了两种日志的实现:JDK的log和log4j的log,当用户没有配置log4j相关的依赖以及配置文件时,获取的实际上是JDK的log打印日志,上面的结果即是JDK的log打印出来的,当添加log4j依赖,并配置好log4j.xml配置文件时,依赖包如下:
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
打印的日志如下:
Hello World!
[2018-03-08 00:31:15 INFO] com.onlyisssilence.muya.App:78 - 日志测试!