java中的日志组件太多了,经常听到的有log4j, slf4j, logbak
等,不太熟悉的有common-logging, JUL, JCL
等,
刚开始接触的时候感觉很晕,不知道这些都是干嘛的,甚至不理解为啥都是记日志的,为什么要整出这么多不同的东西来。后来从头到尾梳理了一遍,才稍微有点清晰。
平时写代码想看看输出结果的时候一般直接用System.out
来输出了,感觉也挺好用的,为什么还要有专门的组件记录日志?
下面给出了几条日志组件应该具有的功能:
日志框架(实现): JUL、 Log4j、 LogBack
日志门面(接口): JCL(common-logging)、 SLF4J
JUL即Java Util Logging
, 是JVM提供的日志组件,在rt.jar
的java.util.logging
包里
common-logging
即Apache Commons Logging
,之前叫Jakarta Commons Logging, JCL
,是apache提供的一个通用的日志接口。
内部有个Simple logger
的简单实现,但很弱,一般配合log4j等第三方实现使用。
slf4j
即Simple Logging Facade for JAVA
,java简单日志门面。类似于Apache Common-Logging
,也是一个日志接口。
SLF4J一般配合第三方实现通过slf4j的桥接包来使用。
Apache的一个开放源代码项目,日志的实现,比较好用,得到了广泛使用。
Log4j有两个版本,一个是log4j1,它使用properties文件进行配置;
另一个是log4j2,跟log4j1不兼容,它使用xml文件进行配置;Log4j2包括两个部分:
log4j-api
日志接口,log4j-core
日志实现。它这么分,有点也想作为日志门面的意思。
Logback是由log4j创始人设计的又一个开源日志组件。
分为三个模块:logback-core,logback-classic
和logback-access
。
logback-core
是其它两个模块的基础模块。logback-classic
是log4j的一个改良版本,并且完整实现了SLF4J API
。
logback-access
访问模块与Servlet容器集成提供通过Http来访问日记的功能。
反正有很多,各有各的用法。JDK里的JUL好像不太好用,后来Log4j得到了广泛应用。
日志组件越来越多,如果一个应用程序中有两个组件,而这两个组件恰好用了不同的日志工具,那这个应用不就有两个日志输出了。
这时候出现了Apache Commons Logging(JCL)
,它只提供log接口,具体的实现则是在运行时动态查找。只要遵守JCL借口的日志工具,都可以通过JCL来使用。
JCL是在运行时动态查找具体的日志实现,当项目很大时,JCL的动态绑定并不是总能成功,解决办法是在项目部署时提前指定绑定哪个日志工具,这就出现了SLF4J。
常用的日志组件有 JUL, Log4j(Log4j1、 Log4j2), Logback
,下面是他们的用法
依赖jdk,无需额外jar包
代码示例:
import java.util.logging.Logger;
public class LogTest {
private static final Logger LOGGER = Logger.getLogger(LogTest.class.getName());
public static void main(String[] args) {
LOGGER.info(LOGGER.getClass().getName());
}
}
结果输出:
五月 23, 2015 4:49:11 下午 com.test.log.LogTest main
信息: java.util.logging.Logger
需要log4j
版本1.2.**
的jar
包
需要properties配置文件(名为log4j.properties
放在classpath下); 无配置文件无法输出日志。
jar包的maven依赖:
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
log4j.properties
配置文件:
log4j.rootLogger = debug, console
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} %m%n
代码示例:
import org.apache.log4j.Logger; // 引入的是类
public class LogTest {
private static final Logger LOGGER = Logger.getLogger(LogTest.class.getName());
public static void main(String[] args) {
LOGGER.debug(LOGGER.getClass().getName());
}
}
结果输出:
2015-05-23 17:44:07 org.apache.log4j.Logger
Log4j2需要log4j-api、log4j-core
版本2.*
的jar
包
需要xml配置文件(名为log4j2.xml
放在classpath下); 不支持properties文件; 无配置文件无法输出日志。
jar包的maven依赖:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.2</version>
</dependency>
log4j2.xml
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
代码示例:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; // 引入的是接口
public class LogTest {
private static final Logger LOGGER = LogManager.getLogger(LogTest.class.getName());
public static void main(String[] args) {
LOGGER.info(LOGGER.getClass().getName());
}
}
结果输出:
18:00:35.409 [main] INFO com.test.log.LogTest - org.apache.logging.log4j.core.Logger
Logback需要logback-core、logback-classic[、slf4j-api]
的jar
包(logback-classic
实现了slf4j-api
)
配置文件:
classpath
中寻找logback.groovy
classpath
中寻找logback-test.xml
classpath
中寻找logback.xml
JVM
的ServiceLoader
实现com.qos.logback.classic.spi.Configurator
logbak
使用自己的BasicConfigurator
配置,将日志输出到控制台jar包的maven依赖:
<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>
logback.xml
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="SYSTEM_OUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="DEBUG">
<appender-ref ref="SYSTEM_OUT" />
</root>
</configuration>
代码示例:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
private static final Logger LOGGER = LoggerFactory.getLogger(LogTest.class.getName());
public static void main(String[] args) {
LOGGER.info(LOGGER.getClass().getName());
}
}
结果输出:
18:00:35.409 [main] INFO com.test.log.LogTest - ch.qos.logback.classic.Logger
JCL需要commons-logging
的jar
包
本文只演示使用方法,对输出结果暂不解释,后面的文章会解释原理
jar包的maven依赖:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
代码示例:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class LogTest {
private static final Log logger = LogFactory.getLog(LogTest.class.getName());
public static void main(String[] args) {
logger.info(logger.getClass().getName());
}
}
结果输出:
五月 23, 2015 7:19:09 下午 com.test.log.LogTest main
信息: org.apache.commons.logging.impl.Jdk14Logger
slf4j只有接口没有实现,必须结合其他日志的实现一起使用