java日志(一):日志组件简介及使用

java中的日志组件太多了,经常听到的有log4j, slf4j, logbak等,不太熟悉的有common-logging, JUL, JCL等, 刚开始接触的时候感觉很晕,不知道这些都是干嘛的,甚至不理解为啥都是记日志的,为什么要整出这么多不同的东西来。后来从头到尾梳理了一遍,才稍微有点清晰。



日志都做什么

平时写代码想看看输出结果的时候一般直接用System.out来输出了,感觉也挺好用的,为什么还要有专门的组件记录日志? 下面给出了几条日志组件应该具有的功能:

  1. 能够在不同阶段输出不同级别的信息
  2. 日志不能影响正常的程序效率
  3. 日志挂了不能影响到正常业务
  4. 还有好多

各个日志组件的介绍

日志框架(实现): JUL、 Log4j、 LogBack
日志门面(接口): JCL(common-logging)、 SLF4J

JUL

JUL即Java Util Logging, 是JVM提供的日志组件,在rt.jarjava.util.logging包里

common-logging

common-loggingApache Commons Logging,之前叫Jakarta Commons Logging, JCL,是apache提供的一个通用的日志接口。 内部有个Simple logger的简单实现,但很弱,一般配合log4j等第三方实现使用。

slf4j

slf4jSimple Logging Facade for JAVA,java简单日志门面。类似于Apache Common-Logging,也是一个日志接口。 SLF4J一般配合第三方实现通过slf4j的桥接包来使用。

Log4j

Apache的一个开放源代码项目,日志的实现,比较好用,得到了广泛使用。
Log4j有两个版本,一个是log4j1,它使用properties文件进行配置;
另一个是log4j2,跟log4j1不兼容,它使用xml文件进行配置;Log4j2包括两个部分: log4j-api日志接口,log4j-core日志实现。它这么分,有点也想作为日志门面的意思。

LogBack

Logback是由log4j创始人设计的又一个开源日志组件。
分为三个模块:logback-core,logback-classiclogback-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,下面是他们的用法

JUL

依赖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

Log4j1

需要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

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需要logback-core、logback-classic[、slf4j-api]jar包(logback-classic实现了slf4j-api)
配置文件:

  1. classpath中寻找logback.groovy
  2. 若无,则在classpath中寻找logback-test.xml
  3. 若无,则在classpath中寻找logback.xml
  4. 若无,则使用JVMServiceLoader实现com.qos.logback.classic.spi.Configurator
  5. 以上都没成功,则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(common-logging)

JCL需要commons-loggingjar
本文只演示使用方法,对输出结果暂不解释,后面的文章会解释原理

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

slf4j只有接口没有实现,必须结合其他日志的实现一起使用