Java内置Logger详解_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java内置Logger详解

Java内置Logger详解

 2013/8/19 0:28:02  MouseLearnJava  程序员俱乐部  我要评论(0)
  • 摘要:平时使用Log4j记录日志信息,对JDK内置的Logger还真没有去关注和使用过,只知道这个是在JDK1.4引入的。这次,抽空去看了一下JDK内置Logger(java.util.logging)。在这篇博文中将记录如下几个方面的信息:1.JDK内置Logger的类结构2.JDK内置Logger支持的Level3.JDK内置Logger支持的Formatter4.JDK内置Logger支持的Handler5.JDK内置Logger默认配置文件6.如何使用JDK内置logger(一
  • 标签:详解 Java
平时使用Log4j记录日志信息,对JDK内置的Logger还真没有去关注和使用过,只知道这个是在JDK 1.4引入的。这次,抽空去看了一下JDK内置Logger(java.util.logging)。在这篇博文中将记录如下几个方面的信息:

1. JDK内置Logger的类结构
2. JDK内置Logger支持的Level
3. JDK内置Logger支持的Formatter
4. JDK内置Logger支持的Handler
5. JDK内置Logger 默认配置文件
6. 如何使用JDK内置logger

(一) JDK内置Logger的类结构

展开java.util.logging包,我们可以看到JDK内置Logger的类,包括Formatter, Handler等。



JDK内置Logger大致的类图关系如下:(方法和关系没有全部标记出来)



(二) JDK内置Logger支持的Level

JDK内置 Logger提供了如下七种Logger级别,从高到低依次是:
SEVERE->WARNING->INFO->CONFIG->FINE->FINER->FINESET。

另外,可以使用OFF关闭日志记录,使用 ALL 启用所有消息的日志记录。

(三) JDK内置Logger支持的Formatter

JDK Logger支持2种Formatter,包括SimpleFormatter 和 XMLFormatter。其中,
SimpleFormatter以文本的形式记录日志信息;XMLFormatter 以XML格式的形式记录日志信息。

(四) JDK内置Logger支持的Handler
Handler,实现将日志写入指定目的地,JDK Logger主要支持MemoryHandler和StreamHandler两个大类Handler,另外ConsoleHanler, FileHandler以及SocketHandler都是继承自StreamHandler,分别添加了一些自己的功能,分别将日志写入控制台、文件、Socket端口。

ConsoleHandler只是将OutputStream设置为System.err,其他实现和StreamHandler类似。

而SocketHandler将OutputStream绑定到对应的端口号中,其他也和StreamHandler类似。另外它还增加了两个配置:java.util.logging.SocketHandler.port和java.util.logging.SocketHandler.host分别对应端口号和主机。

FileHandler支持指定文件名模板(java.util.logging.FileHandler.pattern),文件最大支持大小(java.util.logging.FileHandler.limit,字节为单位,0为没有限制),循环日志文件数(java.util.logging.FileHandler.count)、对已存在的日志文件是否往后添加(java.util.logging.FileHandler.append)。

FileHandler支持的文件模板参数有:
/     目录分隔符
%t    系统临时目录
%h    系统当前用户目录
%g    生成的以区别循环日志文件名
%u    一个唯一的数字以处理冲突问题
%%    一个%

SocketHanlder例子如下:

class="java">package my.logger;

import java.io.IOException;
import java.util.logging.Logger;
import java.util.logging.SocketHandler;

public class SocketHandlerTest {

	private SocketHandler handler = null;

	private static Logger logger = Logger
			.getLogger("my.logger.SocketHandlerTest");

	public SocketHandlerTest(String host, int port) {
		try {
			handler = new SocketHandler(host, port);
			logger.addHandler(handler);
			logger.info("SocketHandler运行成功......");
		} catch (IOException e) {
			logger.severe("请检查地址和端口是否正确......");
			
			StringBuilder sb = new StringBuilder();
			sb.append(e.toString()).append("\n");
			for(StackTraceElement elem : e.getStackTrace())
			{
				sb.append("\tat ").append(elem).append("\n");
			}
			logger.severe(sb.toString());
		}
	}

	public static void main(String args[]) {
		new SocketHandlerTest("localhost", 8080);
	}
}


第一种情况:开启一个Tomcat服务,端口是8080.执行SocketHandlerTest程序,控制输出成功的信息。



第二种情况:关闭Tomcat服务.执行SocketHandlerTest程序,控制输出出错的信息。



再来一个MemoryHanlder的例子:
package my.logger;

import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.MemoryHandler;

public class MemoryHandlerTest {
	public static void main(String[] args) {
		Logger logger = Logger.getLogger("my.logger.MemoryHandlerTest");
	    ConsoleHandler handler = new ConsoleHandler();
	    MemoryHandler mHandler = new MemoryHandler(handler, 10, Level.ALL);
	    logger.addHandler(mHandler);
	    logger.setUseParentHandlers(false);
	    LogRecord record1 = new LogRecord(Level.SEVERE, "This is SEVERE level message");
	    LogRecord record2 = new LogRecord(Level.WARNING, "This is WARNING level message");
	    logger.log(record1);
	    logger.log(record2);

	}

}


(五) JDK内置Logger 默认配置文件
JDK内置Logger默认读取的配置文件是jre\lib\logging.properties
这个可以从LogManager的readConfiguration方法中看出:



logging.properties文件截图如下:



从上述默认配置截图的内容可以看出:
1. handlers默认配置了一个ConsoleHandler, 这个就是为什么我们每次记录信息时,控制台会输出信息的原因,去掉ConsoleHandler,那么在控制台将不会有日志信息输出了。
2. FileHandler默认以XML形式输出。
3. ConsoleHandler默认采用文本形式输出。
4. 默认level为INFO.

5. 如果想指定其它的文件作为logger的配置文件,默认配置文件中提供了如下的信息:
############################################################
Default Logging Configuration File
#
# You can use a different file by specifying a filename
# with the java.util.logging.config.file system property. 
# For example java -Djava.util.logging.config.file=myfile############################################################

另外LogManager中有个public的方法readConfiguration(InputStream ins).
/**
     * Reinitialize the logging properties and reread the logging configuration
     * from the given stream, which should be in java.util.Properties format.
     * A PropertyChangeEvent will be fired after the properties are read.
     * <p>
     * Any log level definitions in the new configuration file will be 
     * applied using Logger.setLevel(), if the target Logger exists.
     * 
     * @param ins	stream to read properties from
     * @exception  SecurityException  if a security manager exists and if
     *             the caller does not have LoggingPermission("control").
     * @exception  IOException if there are problems reading from the stream.
     */
    public void readConfiguration(InputStream ins) throws IOException, SecurityException {
	checkAccess();
	reset();

	// Load the properties
	props.load(ins);
	// Instantiate new configuration objects.
	String names[] = parseClassNames("config");

	for (int i = 0; i < names.length; i++) {
	    String word = names[i];
	    try {
		Class clz = ClassLoader.getSystemClassLoader().loadClass(word);
		clz.newInstance();
	    } catch (Exception ex) {
		System.err.println("Can't load config class \"" + word + "\"");
		System.err.println("" + ex);
		// ex.printStackTrace();
	    }
	}

	// Set levels on any pre-existing loggers, based on the new properties.
	setLevelsOnExistingLoggers();

	// Notify any interested parties that our properties have changed.
	changes.firePropertyChange(null, null, null);

	// Note that we need to reinitialize global handles when 
   	// they are first referenced.
	synchronized (this) {
	    initializedGlobalHandlers = false;
	}
    }


相信这个方法也会是一个实现自定义配置文件的方法。

(六)如何使用JDK内置logger

使用JDK内置Logger可以分成三个步骤来完成:
1. 创建Logger
2. 创建Handler,为handler指定Formmater, 然后将Handler添加到logger中去。
3. 设定Level级别

我们可以自己写一个简单的JDK内置Logger使用的实用类:
package my.logger;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class MyLoggerUtil {

	private static final SimpleDateFormat sdf = new SimpleDateFormat(
			"yyyy-MM-dd");

	private static final String LOG_FOLDER_NAME = "MyLoggerFile";

	private static final String LOG_FILE_SUFFIX = ".log";

	private synchronized static String getLogFilePath() {
		StringBuffer logFilePath = new StringBuffer();
		logFilePath.append(System.getProperty("user.home"));
		logFilePath.append(File.separatorChar);
		logFilePath.append(LOG_FOLDER_NAME);

		File file = new File(logFilePath.toString());
		if (!file.exists())
			file.mkdir();

		logFilePath.append(File.separatorChar);
		logFilePath.append(sdf.format(new Date()));
		logFilePath.append(LOG_FILE_SUFFIX);

		return logFilePath.toString();
	}

	public synchronized static Logger setLoggerHanlder(Logger logger) {
		return setLoggerHanlder(logger, Level.ALL);
	}

	public synchronized static Logger setLoggerHanlder(Logger logger,
			Level level) {

		FileHandler fileHandler = null;
		try {
			//文件日志内容标记为可追加
			fileHandler = new FileHandler(getLogFilePath(), true);

			//以文本的形式输出
			fileHandler.setFormatter(new SimpleFormatter());
			
			logger.addHandler(fileHandler);
			logger.setLevel(level);

			

		} catch (SecurityException e) {
			logger.severe(populateExceptionStackTrace(e));
		} catch (IOException e) {
			logger.severe(populateExceptionStackTrace(e));
		}
		return logger;
	}

	private synchronized static String populateExceptionStackTrace(Exception e) {
		StringBuilder sb = new StringBuilder();
		sb.append(e.toString()).append("\n");
		for (StackTraceElement elem : e.getStackTrace()) {
			sb.append("\tat ").append(elem).append("\n");
		}
		return sb.toString();
	}
}


使用起来也是很方便的。

package my.logger;

import java.util.logging.Logger;

public class JDKLoggerExample {

	
	private static Logger logger = MyLoggerUtil.setLoggerHanlder(Logger.getLogger("my.logger"));

	 public static void main(String[] args) {
		 
		 logger.info("JDK Logger is logging information at INFO Level"); 
	}
}


这样,日志信息就会输出到指定的文件中去,查看一下文件内容如下:





这样,JDK Logger就可以方便的使用起来了。使用时,首先创建一个logger,比如:
private static Logger logger = MyLoggerUtil.setLoggerHanlder(Logger.getLogger("my.logger"));

然后在需要记录日志信息的地方调用logger相应的方法来完成日志信息记录即可。


  • 大小: 65.7 KB
  • 大小: 52.3 KB
  • 大小: 22.6 KB
  • 大小: 120.3 KB
  • 大小: 61.9 KB
  • 大小: 15.8 KB
  • 大小: 42.6 KB
  • 查看图片附件
发表评论
用户名: 匿名