引言
作为一名Java 程序员,最熟悉的、使用最多的调用恐怕莫过于System.out.print(“…”)。当你没有调试工具而要跟踪一个变量的值得时候;当你需要显示捕获的Exception、Error的时候;当你想知道程序在运行的时候究竟发生了什么的时候,通常的做法就是调用System.out.print把他们在终端、控制台上打印出来。这种方式对于输出信息的分类、格式化及永久保存带来诸多不便。虽然我们可以把它写入一个文件然后进行分析,但是这要需要编写额外的程序代码,其成本不可忽视!而由此给目标系统本身增加的复杂程度不可避免的使开发、调试陷入一个深深的迷潭。
JDK1.4的推出,使得这一切即将成为历史。让我们向System.out.print()告别吧,使用Java Logging API为自己的程序构建一个完整的日志记录系统!
一、第一个实例
先看一个简单的实例:SimpleLoggingTest.java
1 import java.util.logging.*;
2 public class SimpleLoggingTest {
3 public static void main(String args[]) {
4 //程序的其它处理
5 //使用Logger的静态方法获得一个匿名 //Logger
6 Logger logger1 = Logger.getAnonymousLogger();
7 //记录消息
8 logger1.log(Level.INFO,"第一条日志记录");
9 //程序的其它处理
10 }
11 }
实例1
注意:编译、执行该程序需要JDK1.4及以上版本的支持。
运行该程序,可以在控制台看到程序运行结果:
2003-1-14 15:09:40 SimpleLoggingTest main
信息: 第一条日志记录
首先,程序引用java.util.Logging包(第1行)。接着,在适当的时候获得一个Logger(记录器)类的实例(第6行,获取一个匿名的Logger)。最后,在程序需要记录信息的地方调用Logger类的log方法进行记录(第8行,记录一个INFO级别的消息)。
二、Java Logging API
Java Logging API封装在JDK1.4.0的java.util.Logging包中。它通过产生便于最终用户、系统管理员、故障维护工程师以及软件开发团队(工程师)进行分析的日志记录为软件的开发调试和维护提供便利的手段。它捕获操作系统平台和执行程序的安全故障、配置错误、执行瓶颈和(或)Bug等数据信息,以纯文本、XML或程序员自定的某种方式将其格式化成日志记录,然后传递给内存、系统输出流、控制台、文件、Sockets等多种系统资源进行缓存和输出。
(一)、该软件包中的关键类。
n Logger: 应用程序进行日志记录调用的主要实体。 Logger对象用于记录特定系统或应用程序的消息。
n LogRecord: 用于在日志框架和单个记录处理程序之间传递记录请求。
n Handler: 日志数据的最终输出处理器。它将LogRecord对象导出到各种目标,包括内存、输出流、控制台、文件和套接字。多种 Handler子类可供用于这种用途。
图一
n Level: 定义一组标准的记录级别,可用于控制记录的输出。可以把程序配置为只输出某些级别的记录,而忽略其他级别的输出。
n Filter: 精细过滤、控制记录的内容,比记录级别所提供的控制准确得多。记录API支持通用的过滤器机制,这种机制允许应用程序代码添加任意过滤器以便控制记录的输出。
n Formatter: 为LogRecord对象的格式化提供支持。
图二
n LogManager: Java Logging框架中唯一的、全局的对象,用于维护与Logger记录器及日志服务的一系列共享的数据结构及状态。它负责整个日志框架的初始化、维护一组全局性的Handle对象、维护一个树形结构的Logger的名字空间、诊测日志框架配置文件的改变从而重新读入并应用相关的参数以及负责程序停止运行时整个日志框架的清理工作。
(二)Logger
1、Logger的命名空间
在SimpleLoggingTest.java实例中,我们使用了一个匿名的(没有命名的)Logger对象。在Java Logging 框架中,Logger是可以命名的。Logger的名字空间与java类的名字空间相同的结构相同:使用“.”间隔的字符串。Logger的名字空间体现了Logger的层次结构。例如:命名为“a.b”的Logger是命名为“a.b.c”的“父”(上一级)Logger记录器。Logger的命名可以是任意的字符串,一般情况下,使用包或类的名字为Logger 进行命名。
Logger的名字空间由全局单列类LogManager的实例进行创建、维护。
匿名Logger不被存储在命名空间中。
2、创建Logger实例
Logger对象可以通过调用工厂方法getLogger或getAnonymousLogger获取。
//获取一个名为“A”的Logger对象
Logger loggerA= Logger.getLogger(“A”);
// 获取一个名为“A.B”的Logger对象,其上级记录器为loggerA。
Logger loggerAB= Logger.getLogger(“A.B”);
//获取一个匿名Logger对象
Logger loggerTmp = Logger.getAnonymousLogger();
对非匿名Logger,getLogger先在命名空间中查找同名的Logger对象,如果有,则返回该Logger对象;如果不存在,则在命名空间中创建注册一个新的Logger对象,并与其上级Logger对象相关联。
匿名Logger对象属于创建它的对象的私有对象,只能由创建它的对象使用,记录一些临时性的日志信息。而命名Logger对象使全局性的,在日志框架的生存期内,除了创建它的对象外还,可由其它对象用于记录日志信息。
匿名的Logger对象由一个全局的的root Logger “” 对象(root Logger的名字为空)。这意味着所有匿名Logger对象将从root Logger “”中继承行为。
匿名Logger对象通常用于java Applet应用中。它去掉了在运行过程中的一班性的安全检查,允许其创建类对象对Logger的控制、状态信息进行修改,如:setLevel设置Logger的日志消息记录级别;addHandle增加Logger的Handle(处理器)对象等。
一个Logger对象可以拥有有零个到多个Handler实例。当没有Handler时,如不禁止日志记录沿名字空间向上传递,那该Logger对象的日志消息记录将有其拥有Handler实例的上级Logger进行处理。当一个Logger对象拥有多个Handler实例对象时,其记录的日志数据将被所有的Handler逐一进行处理。
(三)、Handler
Handler对象接收传来的日志消息将其输出。Handler可以把日志消息输出到多种目标资源,如:输出到控制台进行显示、写入日志文件、传送到网络上的远程日志服务进行处理、写入系统日志等任何物理资源。