zoukankan      html  css  js  c++  java
  • log4j入门(转) --- 很详细 也很简单容易懂

    log4j入门(转)
    Log4j实在是很熟悉,几乎所有的Java项目都用它啊。但是我确一直没有搞明白。终于有一天我受不了了,定下心去看了一把文档,才两个小时,我终于搞明白了。一般情况下Log4j总是和Apache Commons-logging一起用的,我也就一起介绍吧。多了个东西不是更麻烦,而是更简单!
    
    在Log4J中存在几个概念首先介绍一下,最最重要的两个是Logger和Appender(请参考Log4J手册),其实是继承层次以及输出控制。
    
    首先Log4J中总是存在一个rootLogger,即使没有显示配置也是存在的,并且默认输出级别为DEBUG。
    其它的logger都继承自这个rootLogger(如果其他logger未单独定义其输出级别)。
    Log4J中的层次是用'.'来分隔的,如log4j.logger.com.example.test,这里并不是说log4j.logger后面一定是具体的包名乃至类名,
    这个名称可以自定义,我们甚至可以定义一个log4j.logger.A.B.C, 在com.example.test中的类里取名称为A.B的logger,如
    Logger logger = Logger.getLogger("A.B")
    上例中我们建立了3个logger实例,它们分别是"A"、"A.B"、"A.B.C"。每次我们在系统中取得logger时,并不是新建实例,这些实例是系统启动的时候就按照配置文件初始化好的(也可能时第一次引用的时候建立的,然后缓存其实例供以后使用,这部分还没有时间研究)。
    
    限制appender叠加性
    例1:
    log4j.rootLogger=DEBUG, Console
    log4j.logger.A=DEBUG, Console
    log4j.logger.A.B=INFO, Console
    对于logger A.B输出的任何日志会往控制台输出三次,原因是A.B继承A的以及A的父logger的所有appender,
    这种继承关系仅仅是把父logger的appender添加到自己的appender列表中,父logger的输出level不会影响
    子logger的输出。
    
    例2:限制appender叠加
    log4j.rootLogger=DEBUG, Console
    log4j.logger.A=DEBUG, Console
    log4j.logger.A.B=INFO, Console
    log4j.additivity.A.B=false
    logger A.B的日志仅会输出到自己Console中,不会继承任何父logger的appender。
    
    控制appender的输出级别
    若想对输出到appender中的日志级别进行限制的话,就需要用到threshold来控制。
    log4j.threshold=ERROR 用来控制所有的appender,即输出到所有appender的日志,
    不管原来是什么级别的,都不能低于threshold所规定的级别。
    
    log4j.appender.Console.threshold=ERROR 用来控制指定的appender的输出级别。
    
    Log4j的简单思想
    
    Log4j真的很简单,简单到令人发指的地步。不是要记录日志吗?那就给你一个Log,然后你用Log来写东西就行了,先来一个完整类示例:
    
    package test;
    
       
    
    import org.apache.commons.logging.Log;
    
    import org.apache.commons.logging.LogFactory;
    
       
    
    public class Test {
    
            static Log log = LogFactory.getLog(Test.class);
    
       
    
            public void log(){
    
               log.debug("Debug info.");
    
               log.info("Info info");
    
               log.warn("Warn info");
    
               log.error("Error info");
    
               log.fatal("Fatal info");
    
            }
    
       
    
            /**
    
             * @param args
    
             */
    
            public static void main(String[] args) {
    
               Test test = new Test();
    
               test.log();
    
            }
    
    }
    
    别怕,看完这篇文章你就会觉得很简单了。
    
           Log4j默认把日志信息分为五个等级
    
           all<debug < info < warn < error < fatal<off
    
    虽然可以自己添加等级,但是我觉得没有必要,五个够用了吧!你要写入信息的时候就把信息归为五个等级中的一个,然后调用相应的函数即可。
    
           分五个等级到底有什么用呢?日志信息到底写到哪里去了?
    
           “LogFactory.getLog(Test.class)”又是什么意思捏?接着往下看吧!(现在用这个Logger.getLogger(Test.class)吧)
    
    
    Log4j的关键之处在于它的继承思想。也就是一个Log可以继承另外一个Log的属性(输出到哪里,日志等级,日志格式等等)。怎么继承?
    
    Log4j是根据Log的名字来判断继承关系的,比如:
    
    名字为“com.zhlmmc.lib”的Log就是“com.zhlmmc.lib.log”的parent,明白了吧!Log4j还有一个rootLogger,相当于Java的Object。
    
    回过头来看“LogFactory.getLog(Test.class)”这里的“Test.class”事实上传进去的是Test这个类的完整路径(包名+类名),“test.Test”。这样如果存在“test”这个Log那么Test这个Log就继承它,否则就继承rootLogger。
    
           那具体的Log属性是在哪里定义的呢?
    
     
    
    关于logger的两点说明
    用同名参数调用Logger.getLogger(String name)将返回同一个logger的引用。故可以在一个地方配置logger,在另外一个地方获得配置好的logger,而无须相互间传递logger的引用。
    logger的创建可以按照任意的顺序,即,父logger可以后于子logger被创建。log4j将自动维护logger的继承树。
     
    
    常见的配置文件
    
    虽然可以用xml或者在运行时用Java来配置Log4j,但还是properties文件好用啊!
    
    log4j.rootLogger=info, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    
    # Pattern to output the caller's file name and line number.
    
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] (%F:%L) - %m%n
    
    分析一下:
    
    第一行,配置log4j.rootLogger你明白吧。应为它是根,总得配置一下,否则别的Log继承什么啊。其他的Log可以配置也可以不配置。等号后面的第一个参数表示日志级别,可以填五个级别中的一种,后面的参数都是让Log知道输出到哪里,如果你想让日志输出到两个地方就加两个输出参数,比如:
    
    log4j.rootLogger=info, stdout, file
    
    这里的info表示,该Log的日志级别为info,所有级别小于info的日志都不会被记录。比如使用这个配置文件的话,我刚开始举的那个类中
    
    log.debug("Debug info.");
    
    这句话是不起作用的,因为debug的级别小于info。这样就很容易控制什么信息在调试的时候要显示,什么信息在发布的时候要去掉。这些都不用改代码,很方便吧。
    
          
    
    但,stdout和file又是什么呢?
    
    接着往下看,就是配置stdout了,这个名字是随便取的,你可以叫它A:
    
    log4j.appender.A=org.apache.log4j.ConsoleAppender
    
    那么上面的rootLogger的参数stdout也要改成A,其他用到的地方当然也要改。这里的关键不是名字,而是appender类型,比如这里的“ConsoleAppender”,看明白了吧,输出到Console。后面两行都是设置日志格式的,一般情况下你就照抄吧。既然是最简入门关注于理解Log4j的工作原理,我就不介绍file类型的appender了,一搜一大把。
    
    在实际的项目开发中,很可能遇到所引用的包用Log4j来记录日志,比如Hibernate。那么在这里你可以很容易的控制这个包如何记录日志。比如在上面的配置文件中加一行:
    
    log4j.logger.org.hibernate=fatal
    
           那么所有org.hibernate包下面的类就只会显示很少的信息,因为fatal的级别最高啊。
    
    部署
    
    别怕,这可不是部署Tomcat。把log4j的包和commons-logging的包(加在一起才两个)放到classpath下面。然后把配置文件保存为log4j.properties,也放在classpath下面(如果用Eclipse的话,放在src目录下即可)。然后你就可以跑了。
    
     
    
    默认的log4j初始化过程
    Logger类的静态初始化块(static initialization block)中对log4j的环境做默认的初始化。注意:如果程序员已经通过设置系统属性的方法来配置了log4j环境,则不需要再显式地调用XXXConfigurator.configure()方法来配置log4j环境了。
    
    Logger的静态初始化块在完成初始化过程时将检查一系列log4j定义的系统属性。它所做的事情如下:
    
    检查系统属性log4j.defaultInitOverride,如果该属性被设置为false,则执行初始化;否则(只要不是false,无论是什么值,甚至没有值,都是否则),跳过初始化。
    把系统属性log4j.configuration的值赋给变量resource。如果该系统变量没有被定义,则把resource赋值为"log4j.properties"。注意:在apache的log4j文档中建议使用定义log4j.configuration系统属性的方法来设置默认的初始化文件是一个好方法。
    试图把resource变量转化成为一个URL对象url。如果一般的转化方法行不通,就调用org.apache.log4j.helpers.Loader.getResource(resource, Logger.class)方法来完成转化。
    如果url以".xml"结尾,则调用方法DOMConfigurator.configure(url)来完成初始化;否则,则调用方法PropertyConfigurator.configure(url)来完成初始化。如果url指定的资源不能被获得,则跳出初始化过程。
     
    
    Log4j的编码习惯
    让每个类都拥有一个private static的Logger对象,用来输出该类中的全部日志信息
    使用xml文件来完成对log4j环境的配置。在项目的main class中的静态初始化块里放log4j环境的配置代码。注意:在一个项目中,log4j环境只需要被配置一次,而不是在每个使用了logger的类里都需要调用一次
    用MyClass.class作为参数创建该类的静态Logger对象
    
  • 相关阅读:
    JS BOM对象 History对象 Location对象
    JS 字符串对象 数组对象 函数对象 函数作用域
    JS 引入方式 基本数据类型 运算符 控制语句 循环 异常
    Pycharm Html CSS JS 快捷方式创建元素
    CSS 内外边距 float positio属性
    CSS 颜色 字体 背景 文本 边框 列表 display属性
    【Android】RxJava的使用(三)转换——map、flatMap
    【Android】RxJava的使用(二)Action
    【Android】RxJava的使用(一)基本用法
    【Android】Retrofit 2.0 的使用
  • 原文地址:https://www.cnblogs.com/wzhanke/p/4778884.html
Copyright © 2011-2022 走看看