• Java日志


    日志实现流程图

     slf4j只是一个门面(facet),它不包含具体的实现,而是将一些log4j,java.logging等实现包装成统一的接口。

    通过上面的图,可以简单的理清关系!
    commons-logging和slf4j都是日志的接口,供用户使用,而没有提供实现!
    log4j,logback等等才是日志的真正实现。

    当我们调用接口时,接口的工厂会自动寻找恰当的实现,返回一个实现的实例给我服务。这些过程都是透明化的,用户不需要进行任何操作!

    1.log4j

    .概述

      log4j是Apache的一个开源项目,主要是用来做Java开发中的日志管理工作。主要是由三个重要组件构成的。可管理日志的优先级、输出目的地以及输出格式等。它的配置文件主要有XML和properties两种,当然,也可以在程序里配置,但实际开发中一般使用properties文件。

    .log4j的组件

      1.1、日志信息的优先级(Level)

        有7个日志级别:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL,级别从做到有一次降低。

        Off:关闭所有的日志记录

        Fatal:记录严重的错误,并且会导致应用程序退出

        Error:记录严重的错误,但不会影响程序的继续运行

        Warn:记录警告

        Info:记录程序中比较有意义的信息

        Debug:记录程序中的细节信息

        All:记录所有的日志

      1.2、日志信息的输出目的地(Appender)

        log4j可以把日志传送到控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等。

        常用的有以下几种:

        org.apache.log4j.ConsoleAppender(控制台)
        org.apache.log4j.FileAppender(文件)
        org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
        org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生新文件)
        org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
        org.apache.log4j.jdbc.JDBCAppender(将日志信息写到数据库里)

      1.3、日志信息的输出格式(Layout)

         输出格式主要有下边几种:

        org.apache.log4j.HTMLLayout(HTML表格形式)
        org.apache.log4j.PatternLayout(通过表达式指定格式)
        org.apache.log4j.SimpleLayout(仅仅包含日志信息的级别和信息的简单字符串)
        org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

        在使用表达式指定格式的时候,表达式和C的风格还是很相近的,参数如下:    

        %m 输出代码中指定的消息
        %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
        %r 输出自应用启动到输出该log信息耗费的毫秒数
        %c 输出所属的类目,通常就是所在类的全名
        %t 输出产生该日志事件的线程名
        %n 输出一个回车换行符,Windows平台为“rn”,Unix平台为“n”
        %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
        %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)
        %x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
        %%: 输出一个”%”字符 
        %F: 输出日志消息产生时所在的文件名称     %L: 输出代码中的行号     %m: 输出代码中指定的消息,产生的日志具体信息     %n: 输出一个回车换行符,Windows平台为” ”,Unix平台为” ”输出日志信息换行 可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。

      1.4、配置文件格式(properties)

         日志级别设置: 

          log4j.rootLogger = [ level ] , appenderName, appenderName     #级别,输出的目的地1,输出的目的地2,其中appenderName可以任意定义

         输出的目的地:

          #定义appenderName输出到控制器
          log4j.appender.appenderName=org.apache.log4j.ConsoleAppender
          #定义appenderName的布局模式为PaternLayout
          log4j.appender.appenderName.layout=org.apache.log4j.PatternLayout

         输出格式配置:    

          # 定义appenderName的输出格式
          log4j.appender.appenderName.layout.ConversionPattern=%4p [%t] (%F:%L) - %m%n

      

      1.5、加载log4j.properties文件

        1、spring方式加载,配置与web.xml中:

          Spring加载log4j.properties,它提供了一个Log4jConfigListener,本身就能通过web.xml配置从指定位置加载log4j配置文件和log4j的输出路径,要注意的是

        Log4jConfigListener必须要在Spring的Listener之前。

        web.xml   

          <!-- 设置由Sprng载入的Log4j配置文件位置 -->
          <context-param>
            <param-name>log4jConfigLocation</param-name>
            <param-value>WEB-INF/classes/log4j.properties</param-value>
          </context-param>
          <!-- Spring刷新Log4j配置文件变动的间隔,单位为毫秒 -->
          <context-param>
            <param-name>log4jRefreshInterval</param-name>
            <param-value>10000</param-value>
          </context-param>
          <listener>
            <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
          </listener>

        2、可以通过资源类对资源文件进行加载,与使用为一体     

          public class TestLog4j {
          public static void main(String[] args) {
            PropertyConfigurator.configure( " D:/Code/conf/log4j.properties " );
            Logger logger = Logger.getLogger(TestLog4j. class );
            logger.debug( " debug " );
            logger.error( " error " );
          }
          }    

        3、在程序中使用

          在程序中使用Log4j之前,首先要将commons-logging.jar和logging-log4j-1.2.9.jar导入到classpath中,并将log4j.properties放于src根目录中。接下来就可

         以使用了。

        下边是一个完整的配置配置文件,仅供参考:

          #定义输出端
          log4j.rootCategory=INFO,A1,A2,A3

          #定义A1输出到控制器
          log4j.appender.A1=org.apache.log4j.ConsoleAppender
          #定义A1的布局模式为PaternLayout
          log4j.appender.A1.layout=org.apache.log4j.PatternLayout
          # 定义A1的输出格式
          log4j.appender.A1.layout.ConversionPattern=%4p [%t] (%F:%L) - %m%n

          #定义A2输出到文件
          log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
          #定义A2输出到哪个文件
          log4j.appender.A2.File=D:\log\sysLog.log
          #定义A2输出文件的最大长度
          #log4j.appender.A2.MaxFileSize = 1KB
          #定义A2的备份文件数
          #log4j.appender.A2.MaxBackupIndex = 3
          #定义A2的布局模式为PatternLayout
          log4j.appender.A2.layout=org.apache.log4j.PatternLayout
          #定义A2的输出模式
          log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd hh:mm:ss}:%p %t %c - %m%n

          #定义A3输出到数据库
          log4j.appender.A3=org.apache.log4j.jdbc.JDBCAppender
          log4j.appender.A3.URL=jdbc:mysql://localhost:3306/db_log4j
          log4j.appender.A3.driver=com.mysql.jdbc.Driver
          log4j.appender.A3.user=root
          log4j.appender.A3.password=root
          #定义A3的布局和执行的SQL语句
          log4j.appender.A3.layout=org.apache.log4j.PatternLayout
          log4j.appender.A3.layout.ConversionPattern=INSERT INTO tb_log(createDate,thread,level,class,message) values('%d','%t','%-5p','%c','%m')

         Java的测试代码(log4j):

          import org.apache.log4j.Logger;

          public class Log4JTest{

            //1.得到记录器

            Logger logger = Logger.getLogger(Log4JTest.class);
            if(logger.isDebugEnabled()){

              //2.插入记录信息(格式化日志信息)
              logger.debug(new Exception("testLog4j debug demo.").getMessage());
            }
            if(logger.isInfoEnabled()){
              logger.info(new Exception("testLog4j info demo.").getMessage());
            }
            logger.error(new Exception("testLog4j error demo.").getMessage());
            logger.fatal(new Exception("testLog4j fatal demo.").getMessage());

          }

    2、 SLF4J

      如果只使用log4j,每次记录日志的时候需要判断当前的日志级别,例如:

     if(logger.isDebugEnabled()){
        logger.debug(new Exception("testLog4j debug demo.").getMessage());
    }

      但是在使用slf4j时只需要如下:

    logger.debug("Hello world:{}",new Exception("testLog4JSLF4J debug demo.").getMessage());

    slf4j底层会识别日志界别,从而不用自己去判断,大大的简化了书写。

    另外,提供了占位符"{}",使书写布局更加灵活。

    • 降低日志系统的对内存消耗

        slf4j是延迟字符串的加载,上边这段代码的环境中如果日志级别高于debug的话,那么new Exception("testLog4JSLF4J debug demo.").getMessage()这段内

       容将不会被加载。

        另外,占位符减少了日志信息中字符串的拼接,减少了内存和cpu的性能消耗。

    3、slf4j+logback方式的具体实现步骤如下:

    第一步:下载三个jar包,引入jar包(logback-classic_1.0.1.jar,logback-core-1.0.1.jar,slf4j-api-1.6.4.jar),其中logback-classic_1.0.1.jar,logback-core-1.0.1.jar这连个jar包的版本必须一致

    第二步:编写代码测试

    package com.Logger;

    import java.util.Date;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class LoggerTest {
     private static final Logger logger = LoggerFactory.getLogger(LoggerTest.class.getName());

     public static void main(String[] args) {
      logger.info("Current Time: {}", System.currentTimeMillis());
      logger.warn("警告信息:{}", new Date().toString()jie
      
     }

    }

    4、log4j + slf4j 

    第一步:导入的jar包:

      log4j-1.2.17.jar  log4j实现库
      slf4j-api-1.7.7.jar  slf4j库
      slf4j-log4j12-1.7.7.jar  log4j的适配器和静态绑定log4j底层的实现

    第二步:测试代码

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    public class SLF4JTest {   Logger logger = LoggerFactory.getLogger(SLF4JTest.class);   logger.debug("some thing :{}",new Exception("testLog4JSLF4J debug demo.").getMessage());   logger.error(new Exception("testLog4JSLF4J error demo.").getMessage());   logger.info(new Exception("testLog4JSLF4J info demo.").getMessage());
    }

      

  • 相关阅读:
    图解VS2008单元测试及查看代码覆盖率
    Effective C++:条款02:尽量以const, enum, inline替换#define (Prefer consts, enums, and inline to #defines.)
    Effective C++:条款01:视C++为一个语言联邦(View C++ as a federation of languages.)
    Effective C++:条款03:尽可能使用const (Use const whenever possible.)
    mysql foreign key <转>
    Linux下Apache绑定多个域名的方法 <转>
    python(1)input()和raw_input
    《精通CSS》读书笔记(1)
    CSS相对定位和绝对定位
    【分享】沪江网提供的每日一句API
  • 原文地址:https://www.cnblogs.com/xp0813/p/12270010.html
Copyright © 2020-2023  润新知