《编程语言java之log4j教程》由会员分享,可在线阅读,更多相关《编程语言java之log4j教程(13页珍藏版)》请在金锄头文库上搜索。
1、编程语言编程语言 javajava 之之 log4jlog4j 教程教程为什么不用 System.out.println()? 功能太弱;不易于控制。如果暂时不想输出了怎么办?如果想输出到文件怎么办?如果想部分输出怎么办? 为什么同时使用 commons-logging 和 Log4j?为什么不仅使用其中之一? Commons-loggin 的目的是为“所有的 Java 日志实现”提供一个统一的接口,它自身的日志功能平常弱(只有一个简单的SimpleLog?) ,所以一般不会单独使用它。 Log4j 的功能非常全面强大,是目前的首选。我发现几乎所有的Java 开源项目都会用到 Log4j,但我
2、同时发现,所有用到 Log4j 的项目一般也同时会用到 commons-loggin。我想,大家都不希望自己的项目与 Log4j 绑定的太紧密吧。另外一个我能想到的“同时使用 commons-logging 和 Log4j”的原因是,简化使用和配置。 强调一点, “同时使用 commons-logging 和 Log4j” ,与“单独使用Log4j”相比,并不会带来更大的学习、配置和维护成本,反而更加简化了我们的工作。我想这也是为什么“所有用到 Log4j 的项目一般也同时会用到commons-loggin”的原因之一吧。 Commons-logging 能帮我们做什么? l ) 提供一个统一
3、的日志接口,简单了操作,同时避免项目与某个日志实现系统紧密耦合 2) 很贴心的帮我们自动选择适当的日志实现系统(这一点非常好!) 3) 它甚至不需要配置 这里看一下它怎么“很贴心的帮我们自动选择 适当的日志实现系统”: 1)首先在 classpath 下寻找自己的配置文件 commons-logging.properties,如果找到,则使用其中定义的 Log 实现类; 2)如果找不到 commons-logging.properties 文件,则在查找是否已定义系统环境变量 mons.logging.Log,找到则使用其定义的 Log 实现类; 3)否则,查看 classpath 中是否有
4、Log4j 的包,如果发现,则自动使用 Log4j 作为日志实现类; 4)否则,使用 JDK 自身的日志实现类(JDK1.4 以后才有日志实现类); 5) 否则,使用 commons-logging 自己提供的一个简单的日志实现类SimpleLog; (以上顺序不保证完全准确,请参考官方文档) 可见,commons-logging 总是能找到一个日志实现类,并且尽可能找到一个“最合适”的日志实现类。我说它“很贴心”实际上是因为:1、可以不需要配置文件;2、自动判断有没有 Log4j 包,有则自动使用之;3、最悲观的情况下也总能保证提供一个日志实现(SimpleLog) 。 可以看到,commo
5、ns-logging 对编程者和 Log4j 都非常友好。 为了简化配置 commons-logging,一般不使用 commons-logging 的配置文件,也不设置与 commons-logging 相关的系统环境变量,而只需将 Log4j 的 Jar 包放置到 classpash 中就可以了。这样就很简单地完成了 commons-logging 与 Log4j 的融合。如果不想用 Log4j 了怎么办?只需将 classpath 中的 Log4j 的 Jar包删除即可。 代码应该怎么写? 我们在需要输出日志信息的“每一人”类中做如下的三个工作: 1、导入所有需的 commongs-lo
6、gging 类: import mons.logging.Log; import mons.logging.LogFactory; 2、在自己的类中定义一个 mons.logging.Log 类的私有静态类成员: private static Log log = LogFactory.getLog(YouClassName.class); 注意这里定义的是 static 成员,以避免产生多个实例。 LogFactory.getLog()方法的参数使用的是当前类的 class,这是目前被普通认为的最好的方式。为什么不写作LogFactory.getLog(this.getClass()?因为 s
7、tatic 类成员访问不到 this 指针! 3、使用 mons.logging.Log 类的成员方法输出日志信息: log.debug(“111“); log.info(“222“); log.warn(“333“); log.error(“444“); log.fatal(“555“); 这里的 log,就是上面第二步中定义的类成员变量,其类型是mons.logging.Log,通过该类的成员方法,我们就可以将不同性质的日志信息输出到目的地(目的地是哪里?视配置可定,可能是 stdout,也可能是文件,还可能是发送到邮件,甚至发送短信到手机详见下文对 log4j.properties 的介
8、绍): debug() 输出“调试”级别的日志信息; info() 输出“信息”级别的日志信息; warn() 输出“警告”级别的日志信息; error() 输出“错误”级别的日志信息; fatal() 输出“致命错误”级别的日志信息; 根据不同的性质,日志信息通常被分成不同的级别,从低到高依次是:“调试(DEBUG) ” “信息(INFO) ” “警告(WARN) ” “错误(ERROR) ” “致命错误(FATAL) ” 。为什么要把日志信息分成不同的级别呢?这实际上是方便我们更好的控制它。比如,通过 Log4j 的配置文件,我们可以设置“输出调试及以上级别的日志信息”(即“调试” “信息
9、” “警告” “错误” “致命错误” ) ,这对项目开发人员可能是有用的;我们还可以设置“输出“警告”及以上级别的日志信息” (即“警告” “错误” “致命错误” ) ,这对项目最终用户可能是有用的。 仅从字面上理解,也可以大致得出结论:最常用的应该是 debug()和 info();而 warn()、error()、fatal()仅在相应事件发生后才使用。 从上面三个步骤可以看出,使用 commons-logging 的日志接口非常的简单,不需要记忆太多东西:仅仅用到了两个类 Log, LogFactory,并且两个类的方法都非常少(后者只用到一个方法,前者经常用到的也只是上面第三步中列出的
10、几个) ,同时参数又非常简单。 下面给出一个完整的 Java 类的代码: package liigo.testlog; import mons.logging.Log; import mons.logging.LogFactory; public class TestLog private static Log log = LogFactory.getLog(TestLog.class); public void test() log.debug(“111“); log.info(“222“); log.warn(“333“); log.error(“444“); log.fatal(“555
11、“); public static void main(String args) TestLog testLog = new TestLog(); testLog.test(); 只要保证 commons-logging 的 jar 包在 classpath 中,上述代码肯定可以很顺利的编译通过。那它的执行结果是怎么样的呢?恐怕会有很大的不同,请继续往下看。 Log4j 在哪里呢?它发挥作用了吗? 应该注意到,我们上面给出的源代码,完全没有涉及到 Log4j这正是我们所希望的,这也正是 commons-logging 所要达到的目标之一。 可是,怎么才能让 Log4j 发挥它的作用呢?答案很简
12、单,只需满足“classpath 中有 Log4j 的 jar 包” 。前面已经说过了,commons-logging 会自动发现并应用 Log4j。所以只要它存在,它就发挥作用。 (它不存在呢?自然就不发挥作用,commons-logging 会另行选择其它的日志实现类。 ) 注意:配置文件 log4j.properties 对 Log4j 来说是必须的。如果classpath 中没有该配置文件,或者配置不对,将会引发运行时异常。 Log4j 中有三个主要的组件,它们分别是 Logger、Appender 和LayoutLog4j 允许开发人员定义多个 Logger,每个 Logger 拥有
13、自己的名字,Logger 之间通过名字来表明隶属关系。一个 Log 可以继承另外一个 Log 的属性(输出到哪里,日志等级,日志格式等等) 。怎么继承?Log4j 是根据 Log 的名字来判断继承关系的,比如:名字为“cn.dahe.lib”的 Log 就是“cn.dahe.lib.log”的 parent,明白了吧!Log4j 还有一个 rootLogger,相当于 Java 的 Object。回过头来看“LogFactory.getLog(Test.class)”这里的“Test.class”事实上传进去的是 Test 这个类的完整路径(包名+类名) ,“test.Test” 。这样如果存
14、在“test”这个 Log 那么 Test 这个 Log就继承它,否则就继承 rootLogger。rootLogger,它永远存在,且不能通过名字检索或引用,可以通过Logger.getRootLogger()方法获得,其它 Logger 通过 Logger.getLogger(String name)方法。Appender 则是用来指明将所有的 log 信息存放到什么地方,一个Logger 可以拥有多个 Appender,也就是你既可以将 Log 信息输出到屏幕,同时存储到一个文件中。Layout 的作用是控制 Log 信息的输出方式,也就是格式化输出的信息参数的意义输出级别的种类ERRO
15、R、WARN、INFO、DEBUGERROR 为严重错误 主要是程序的错误WARN 为一般警告,比如 session 丢失INFO 为一般要显示的信息,比如登录登出DEBUG 为程序的调试信息配置日志信息输出目的地log4j.appender.appenderName = fully.qualified.name.of.appender.class1.org.apache.log4j.ConsoleAppender(控制台)2.org.apache.log4j.FileAppender(文件)3.org.apache.log4j.DailyRollingFileAppender(每天产生一个日
16、志文件)4.org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)5.org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)配置日志信息的格式log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class1.org.apache.log4j.HTMLLayout(以 HTML 表格形式布局) ,2.org.apache.log4j.PatternLayout(可以灵活地指定布局模式) ,3.org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串) ,4.org.apache.lo