zoukankan      html  css  js  c++  java
  • SLF4J 的几种实际应用模式 SLF4J+Log4J 与 SLF4J+LogBack


    SLF4J(Simple Logging Facade for Java) 是一个通用的日志框架,不能何以谓之 Facade(门面),所扮眼的角色相当于 Jakarta Commons Logging。就像 JCL 需要底层的日志实现,如 Log4J、java.util.logging、Simple Logger 等来完成具体的信息输出,事实上基本总是 JCL+Log4J 那么一个绝配。SLF4J 的原旨也是能支持多种下层日志框架实现,但最好的日志实现仍然是 Log4J,所以本篇讲述 SLF4J 的第一种用法 SLF4J+Log4J。

    需要的配置文件和组件包,下面三个 jar 文件和一个 properties 文件都是要放在项目的 ClassPath 上。

    1. slf4j-api-1.5.11.jar
    2. slf4j-log4j12-1.5.11.jar
    3. log4j-1.2.15.jar
    4. log4j.properties(也可以是 log4j.xml,本例中用 log4j.propertes)

    前两个包在 http://www.slf4j.org/download.html 处下载,后一个包在 http://logging.apache.org/log4j/1.2/download.html 下载,可能包文件名中的版本号有些差,不要紧。

    log4j.properties 以前该是怎么写,现在还是怎么写,比如一个最简单的内容,只向控制台输出日志信息,如下:

    view source
    print?
    1.log4j.rootLogger=DEBUG,console 
    2.log4j.appender.console=org.apache.log4j.ConsoleAppender  
    3.log4j.appender.console.layout=org.apache.log4j.PatternLayout  
    4.log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n

    使用 SLF4J  的代码:

    view source
    print?
    01.package com.unmi;
    02.
    03.import org.slf4j.Logger;
    04.import org.slf4j.LoggerFactory;
    05.
    06.public class TestSlf4j {
    07.    private static final Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
    08.
    09.    public static void main(String[] args) {
    10.        logger.info("Hello {}","SLF4J");
    11.    }
    12.}

    执行它,控制台输出:

    2010-04-07 17:14:51,390 [com.unmi.TestSlf4j]-[INFO] Hello SLF4J

    把这种 SLF4J+Log4J 的使用模式与曾为霸主地位的 JCL+Log4J 的用法进行一下对比(请忽略掉包文件中的版本号):

    SLF4J+Log4j 组合 对比 JCL+Log4J 组合
    slf4j-api-1.5.11.jar 相当,定义高层 API commons-logging-1.1.jar
    slf4j-log4j12-1.5.11.jar 相当,左边是用绑定包,右边
    是用配置文件来指定日志实现 commons-logging.properties,内容为:
    org.apache.commons.logging.LogFactory=
    org.apache.commons.logging.impl.LogFactoryImpl
    或者
    org.apache.commons.logging.Log=
    org.apache.commons.logging.impl.Log4JLogger
    log4j-1.2.15.jar 一样 log4j-1.2.15.jar
    log4j.properties 一样,原来怎么配置现在也是 log4j.properties
    程序代码中:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
    logger.info("Hello {}","SLF4J"); 左边侵入的是 SLF4J API,右边是被 JCL 的 API 污染了

    SLF4J 支持参数化,而 JCL 不能 程序代码中:
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    Log log = LogFactory.getLog(TestJCL.class);

    log.info("Hello JCL");

    从上面的对比来看,SLF4j+Log4j 与 JCL+Log4J 的使用方式差不多,主要差异就在 SLF4J 用 jar 来告知用哪种日志实现,而 JCL 是通过配置文件来获得该选择哪个日志实现。

    为什么会兴起 SLF4J,看看我们原来哪一个框架中,大的如 SSH 三雄(Spring、Struts、Hibernate),还有 WAS 应用服务器,小的就不计其数以前用的通用日志框架都清一色的 Jakarta Commons Logging(JCL),日志实现会选用 Log4j,为何现在 Hibernate、Tapesty、DbUnit、Jetty V6 等纷纷变节,都采用了 SLF4J 了呢?SLF4J 与 JCL 相比,定然是有其可表之处。而其中 SLF4J 受类加载器的影响较小,不易产生内存溢出的问题,性能得到了改善,更主要是顺应了潮流的发展--可方便部署到 OSGI 环境中
    ----------------------------------------------------------------------------------------------------------------------------------------------------
    二 》SLF4J+LogBack
    前面讲的 SLF4J 的用法之一是 SLF4J+Log4J,而这里要推出的组合是 SLF4J+LogBack。不用 Log4J?难道还有比 Log4J 更好的日志实现吗?是的,答案就是 LogBack。假如你知道 LogBack 和 Log4J 是同出一位大师之手,你就不会觉得惊讶了。LogBack 对 Log4J 进行了增强,并投入了 SLF4J 的怀抱,它还被作者认定为 Log4J 的继任者。

    为什么叫做 Logback,我就不知道了,反正不要叫做 Brokeback 就行。这里是推崇用 Logback 替代 Log4J 的十几个理由:Reasons to prefer logback over log4j,说的大至是更快;好测试;与 SLF4J 关系紧;文档丰富;能自动加载配置文件;多个 JVM 写一个日志文件,或其他 I/O 错误时不影响程序执行;配置文件中加入条件控制;强大的日志过滤;更强的日志切分功能;自动压缩、删除日志文件;异常栈中更多的数据信息。

    Logback 分为三个模块:logback-core,logback-classic,logback-access。logback-core 是核心;logback-classic 改善了 log4j,且自身实现了 SLF4J API,所以即使用 Logback 你仍然可以使用其他的日志实现,如原始的 Log4J,java.util.logging 等;logback-access 让你方便的访问日志信息,如通过 http 的方式。

    还得提一点,Logback 能更好的放到 OSGI 环境中。好了,简单绍完了 Logback,就来看看具体怎么用它。

    需要的配置文件和组件包,下面三个 jar 文件和一个 xml文件都是要放在项目的 ClassPath 上。

    1. slf4j-api-1.5.11.jar
    2. logback-core-0.9.20.jar
    3. logback-classic-0.9.20.jar
    4. logback.xml 或 logback-test.xml (类似于 log4j.properties/log4j.xml)

    前一个包在 http://www.slf4j.org/download.html 处下载,第二第三个包在 http://logback.qos.ch/download.html 下载,可能包文件名中的版本号有些差,不要紧。由于这里不演示 HTTP 访问日志信息,所以不需要用到 logback-access-0.9.20.jar。

    Logback 先找 logback-test.xml,没有则找 logback.xml 文件,都找不到就使用 BasicConfigurator 基本配置,BasicConfigurator 就是相当于等会贴出的 logback.xml 文件内容的配置。这里我们用 logback.xml 配置文件,以前的 log4j.properties  文件可以用 PropertiesTranslator 转换成 logback.xml 文件内容。

    下面是一个最简单的 logback.xml 文件内容

    view source
    print?
    01.<?xml version="1.0" encoding="UTF-8"?>
    02.<configuration>
    03.  <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
    04.      <encoder charset="GBK">
    05.          <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    06.      </encoder>
    07.  </appender>
    08.   
    09.  <root level="DEBUG">
    10.    <appender-ref ref="stdout" />
    11.  </root>
    12.</configuration>

    在 log4j.xml 能做的配置,logback.xml 中也能做到,而且还增强了诸如 <if><then><else>、<filter>、<sift> 等更强的控制,请参考 logback 的手册 http://logback.qos.ch/manual/index.html。

    使用 Logback  的代码

    view source
    print?
    01.package com.unmi;
    02.
    03.import org.slf4j.Logger;
    04.import org.slf4j.LoggerFactory;
    05.
    06.public class TestLogback {
    07.    private static final Logger logger = LoggerFactory.getLogger(TestLogback.class);
    08.
    09.    public static void main(String[] args) {
    10.        logger.info("Hello {}","TestLogback");
    11.    }
    12.}


    可以看到与使用 SLF4J 的代码没有任何区别,因为本来用的通用日志框架就是 SLF4J,说到底,这里的 Logback 就相当于 SLF4J+Log4J 使用方式中的 Log4J 绑定和 Log4J 的功能。

    执行上面的代码,输出:

    21:38:43.031 [main] INFO  com.unmi.TestLogback - Hello TestLogback

    还是和上次一样,这里就拿 SLF4J+Logback 和 SLF4J+Log4J 两种方式作下比较:

    SLF4J+Logback 组合 对比 SLF4J+Log4J 组合
    slf4j-api-1.5.11.jar 一样的,定义高层 API slf4j-api-1.5.11.jar
    logback-classic-0.9.20.jar 都是用绑定,
    左边这里用作
    Logback 绑定 slf4j-log4j12-1.5.11.jar
    logback-classic-0.9.20.jar 左边这里用作
    日志实现 log4j-1.2.15.jar
    logback-test.xml/logback.xml 相当,logback 增加
    了 log4j log4j.properties/log4j.xml
    程序代码中:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    Logger logger = LoggerFactory.getLogger(TestSlf4j.class);
    logger.info("Hello {}","SLF4J"); 完全一样,实质上只是
    SLF4J API
    侵入到了应用组件
    中了,与 Logback
    没有关系。 程序代码中:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    Logger logger = LoggerFactory.getLogger(TestLogback.class);
    logger.info("Hello {}","Logback");

    通过上面我们更清楚的发现,SLF4J+Logback 这样的组合与 SLF4J+Log4J 这样的用法其实没有什么差异。SLF4J 在使用其他日志实现框架的时候都是 SLF4J+相应绑定+日志实现,这里缩写成的 SLF4J+Log4J,中间是有一个 SLF4J 到 Log4J 的绑定的。完整表述它们就是:

    SLF4J+Log4J 的方式:    slf4j-api-1.5.11.jar + slf4j-log4j12-1.5.11.jar + log4j-1.2.15.jar
    SLF4J+Logback 的方式:slf4j-api-1.5.11.jar + logback-classic-0.9.20.jar + logback-classic-0.9.20    前一个 logback-classic-0.9.20.jar 是作为绑定用的,后一个是作为日志实现用的,也就是 logback-classic-0.9.20.jar 把前面的 slf4j-log4j12-1.5.11.jar 和 log4j-1.2.15.jar 两个包的功能揉合在了一起。

    搞明白了 Logback 在其中所担当的角色后,我们就知道,说使用了 Logback 应用组件,实际它们所用的统一日志组件只是 SLF4J。也可以说 Logback 就是 Log4J 那样,只是自身带了绑定的日志实现。

    在 Logback 官方首页 http://logback.qos.ch/ 面中可以看到使用了 Logback 的项目。
    复杂一点的 logback.xml
    <configuration>

        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d [%thread | %logger.%method\(%file:%line\)] %-5level - %msg%n</pattern>
            </encoder>
        </appender>
        
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>adcapture.log</file>

            <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
                <fileNamePattern>adcapture.%i.log</fileNamePattern>
                <minIndex>1</minIndex>
                <maxIndex>10</maxIndex>
            </rollingPolicy>

            <triggeringPolicy
                class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
                <maxFileSize>1KB</maxFileSize>
            </triggeringPolicy>
            <encoder>
                <pattern>%d [%thread | %logger.%method\(%file:%line\)] %-5level - %msg%n</pattern>
            </encoder>
        </appender>

        <root level="DEBUG">
            <appender-ref ref="STDOUT" />
            <appender-ref ref="FILE" />
        </root>
    </configuration> 

    补充:

    除了使用默认的日志主线程 <root> 外,还可以通过 <logger> 标签定制其他日志线程如:

    copy

    1. <logger name="com.test" level="DEBUG">  
    2.         <appender-ref ref="STDOUT" />  
    3.       </logger>  

    其中 name 指定线程针对的包路径,level 是日志级别,<appender-ref> 定义使用哪种 appender。

    例如要实现打印 jdbc 提交的 sql,可以加入如下 logger:

    <logger name="java.sql.Connection" level="DEBUG"><appender-ref ref="STDOUT" /></logger>

    贴出使用了该策略的logback.xml

    [xhtml] view plaincopy
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <configuration>  
    3.   <!-- log output to file  -->  
    4.   <appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">  
    5.     <file>E:/logs/mylog.txt</file>  
    6.     <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">  
    7.       <!-- rollover daily -->  
    8.       <fileNamePattern>E:/logs/mylog-%d{yyyy-MM-dd_HH-mm}.%i.log</fileNamePattern>  
    9.       <maxHistory>5</maxHistory>   
    10.       <timeBasedFileNamingAndTriggeringPolicy  
    11.             class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">  
    12.         <!-- or whenever the file size reaches 100MB -->  
    13.         <maxFileSize>100MB</maxFileSize>  
    14.       </timeBasedFileNamingAndTriggeringPolicy>  
    15.     </rollingPolicy>  
    16.     <encoder>  
    17.       <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n</pattern>  
    18.     </encoder>  
    19.   </appender>  
    20. <!-- log output to console  -->  
    21. <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">  
    22.     <encoder>  
    23.       <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>  
    24.     </encoder>  
    25.   </appender>  
    26. <!--  log output to db-->  
    27. <appender name="DB" class="ch.qos.logback.classic.db.DBAppender">  
    28.     <connectionSource class="ch.qos.logback.core.db.DriverManagerConnectionSource">  
    29.        <dataSource  
    30.         class="com.mchange.v2.c3p0.ComboPooledDataSource">  
    31.       <driverClass>com.mysql.jdbc.Driver</driverClass>  
    32.       <url>jdbc:mysql://127.0.0.1:3306/tunneldb</url>  
    33.       <user>root</user>  
    34.       <password>123123</password>  
    35.       </dataSource>  
    36.     </connectionSource>  
    37.   </appender>  
    38.   
    39.     <logger name="com.ttt.ttt" level="DEBUG">  
    40.         <appender-ref ref="STDOUT" />  
    41.     </logger>  
    42.    
    43.     <logger name="java.sql.Connection" level="DEBUG"><appender-ref ref="STDOUT" /></logger>  
    44.      <!--  打印sql  
    45.     <logger name="java.sql.Statement" level="DEBUG"><appender-ref ref="STDOUT" /></logger>  
    46.     <logger name="java.sql.PreparedStatement" level="DEBUG"><appender-ref ref="STDOUT" /></logger>  
    47.       
    48.     <logger name="java.sql.ResultSet" level="DEBUG"><appender-ref ref="STDOUT" /></logger>  
    49.     -->  
    50.   <root level="DEBUG"><appender-ref ref="ROLLING" /></root>  
    51. </configuration>  


  • 相关阅读:
    leetcode131分割回文串
    leetcode315 计算右侧小于当前元素的个数
    Tensorflow写代码流程&反向传播
    vue脚手架的搭建
    Vue 脱坑记
    简历中的工作经历要怎么写?
    如何制作高水平简历?
    window.location.hash的知识点
    前端面试题小集
    前端面试题
  • 原文地址:https://www.cnblogs.com/leonxyzh/p/7289178.html
Copyright © 2011-2022 走看看