您的位置:首页 > 编程语言 > Java开发

Java程序调试与日志进阶

2012-03-09 00:00 302 查看

概述

本文根据作者的开发经验叙述了对Java程序调试和日志的认识和理解。介绍了System.out.println, System.out.printf,手工制作的小工具类SysUtils.log,log4j和logback。

引言

在Java开发中,除了IDE提供的调试工具之外,监控代码中变量变化,跟踪代码运行有很多种方法:

1、招之即来的System.out.println

System.out.println无疑是最方便的,受众也是最广,知名度最高。Java学习者往往从第一个HelloWorld的例子开始就接触它,学习Java的人应该没有人不知道它。
示例代码:
System.out.println(sql);
System.out.println("My name is " + name + ", I am " + age + " years old.");
优点是显而易见的,缺点也不少,如:
只能输出到控制台;
大量的代码混在业务逻辑中,在生产环境中需要处理这些影响性能的代码。
字符串拼接容易带来性能损失(当然可以使用StringBuffer,但又稍显繁琐)

2、Java5对System.out.println的改进:System.out.printf

转向Java的C程序员无比怀念C语言中的printf,Java5也对此提供了支持,Java也开始为开发者着想了,看代码:
System.out.println(sql);
System.out.printf("My name is %S, I am %d years old.", name, age);

C程序员对此最熟悉不过了,无论是可读性和效率都比上面的好很多,唯一的缺点就是需要Java 5 的支持。

3、土制的utils小工具

System.out.println,带来的最大问题是从开发环境向生产环境转换时带的性能问题(当然其它的问题也不少),部署时应该去除或注释这些代码,。
解决这个问题最好的办法是土制一个小工具类,look:
public class SysUtils {
public static final void log(Object o) {
System.out.println("==" + String.valueOf(o));
}
}
以后的调试代码全部调用上面的静态方法,代码如下:
SysUtils.log(sql);
SysUtils.log("My name is " + name + ", I am " + age + " years old.");

部署的时候,只要把SysUtils.log里的System.out.println 注释掉就万事大吉了。

4、进阶过程,日志小知识

然而一切似乎还是没有改变,功能太弱,和代码耦合性太强...于是日志(log)出现了。日志,源于log,有航海日志的意思。指记录海员记录每天的行程,生活及发生的事件。在软件开发领域,用来监控代码中变量变化,跟踪代码运行的轨迹,在开发环境中担当调试器作用,向控制台或文件输出信息,运行环境中记录程序的警告和错误信息。
Java开源牛人们为了改变现状,不断开发出各种各样的日志工具,于是Java程序员受苦了,不得不在各种日志间转换奔波。
然而天下大事,分久必合,合久必分。于是乎commons-logging出现了。它提供了日志统一的接口和一个最简单的实现。Java程序员幸福了,因为只需要针对接口编程。而不管到底由谁来实现。

最著名的几个实现有:
Simplelog:最简单的实现。
Jul:java.util.logging,JDK中自带的日志实现
log4j:Apache Software Foundation开发的非常强大的日志实现

log主要有几个个概念:
输出级别:是调试信息,信息,还是警告,错误,致命错误等
输出目的地:输出到控制台,文件,可写设备,还是数据库
输出格式和内容:输出哪些东西,如何排版等。

5、log4J

Log4J的意思是Log for Java,4是for的简写,当然也读作 “for”

Log4J的输出级别:
Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。
Log4J的输出目的地:
ConsoleAppender(控制台)
FileAppender(文件)
DailyRollingFileAppender(每天产生一个日志文件)
RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
WriterAppender(将日志信息以流格式发送到任意指定的地方)
甚至能输出到数据库
Log4J的输出格式:
HTMLLayout(以HTML表格形式布局)
PatternLayout(可以灵活地指定布局模式)
SimpleLayout(包含日志信息的级别和信息字符串)
TTCCLayout(包含日志产生的时间、线程、类别等等信息)
Log4J的输出内容:
Log级别
类名
线程名
时间
位置等等。
强大到足以在开发环境或生产环境做一切你能想到的记录。

Log4J在Java Web项目中的使用方法:
1. commons-logging.jar, log4.jar扔到lib目录
2. log4j.properties文件扔到classes根目录
3. OK了。

示例代码:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class TestLog {
Log log = LogFactory.getLog(TestLog.class);
public void print() {
if (log.isDebugEnabled()) {
log.debug (sql);
log.debug ("My name is " + name + ", I am " + age + " years old.");
}
}
}

6、slf4j和logback,没有最好,只有更好

log4j经过这么久的发展,从外面看,经典,庄重,强壮,从内部看,却充满了代码的坏味道。就连它的作者也认为应该有一个更好的日志框架。于是,再次操刀,创建了slf4j来取代jcl,创建了logback来取代log4j。
目前,log4j和jul应用最为广泛,slf4j作为新兴的抽象层,整合logback,以其简洁,快速,正被越来越多的顶级项目使用。如大名鼎鼎的hibernate,Jetty。
参见:http://www.slf4j.org/

十个转移到logback的理由http://logback.qos.ch/10reasons.ppt

slf4j支持参数化的logger.error("帐号ID:{}不存在", userId);告别了if(logger.isDebugEnable()) 时代。

另外logback的整体性能比log4j也较佳,hibernate等项目已经采用了slf4j:

"某些关键操作,比如判定是否记录一条日志语句的操作,其性能得到了显著的提高。这个操作在LOGBack中需要3纳秒,而在Log4J中则需要30纳 秒。 LOGBack创建记录器(logger)的速度也更快:13毫秒,而在Log4J中需要23毫秒。更重要的是,它获取已存在的记录器只需94纳秒,而 Log4J需要2234纳秒,时间减少到了1/23。"

Slf4j 相当于commons-logging 提供了一系列的日志接口
Logback相当于 log4j 提供了强大的实现

作者也称Logback是可靠,通用,快速,灵活的java日志工具(官方描述)。

commons-logging 和slf4j的代码比较:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestLogBySlf4J {
Logger logger = LoggerFactory.getLogger(TestLogBySlf4J.class);
public void print() {
logger.debug(sql);
logger.debug("My name is {}, I am {} years old.", name, age);
}
}

依稀又有了一点Java5的影子。

项目选择的思考。

如果是简单的项目,如小工具,小Demo等,采用System.out.printf , 土制工类,jul,都是不错的选择。

如果是web开发,宜采用log4j,因为系统已经有了很多的配置文件,不在乎多一个,而且功能强大。公司目前很多项目采用log4j。

如果是较新的项目,可采用slf4j,在学习成本不高的情况下,获得更好的架构,灵活性和性能。

小结

限于篇幅,本文只简要介绍了从原始的内置类到简单的封装,再到Log4j,再到强大的logback的进阶过程和主要示例代码,中间细节请查阅官方详细的文档。

参考资料

Slf4j官方网站(http://www.slf4j.org/)。
Logback官方网站(http://logback.qos.ch/)。

Jcl官方网站(http://commons.apache.org/logging/)。

Log4j官方网站(http://logging.apache.org/)。
SpringSide 官方wiki(http://wiki.springside.org.cn/)。

Java日志系统研究(http://yanboy.javaeye.com/blog/204436

关于作者

kimsoft

$(document).ready(function(){dp.SyntaxHighlighter.HighlightAll('code');});

原文链接:
http://blog.csdn.net/kimsoft/article/details/3325575
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: