Java内置Logger详解

平时使用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 的例子如下: 

Java代码   收藏代码
  1. package my.logger;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.logging.Logger;  
  5. import java.util.logging.SocketHandler;  
  6.   
  7. public class SocketHandlerTest {  
  8.   
  9.     private SocketHandler handler = null;  
  10.   
  11.     private static Logger logger = Logger  
  12.             .getLogger("my.logger.SocketHandlerTest");  
  13.   
  14.     public SocketHandlerTest(String host, int port) {  
  15.         try {  
  16.             handler = new SocketHandler(host, port);  
  17.             logger.addHandler(handler);  
  18.             logger.info("SocketHandler运行成功......");  
  19.         } catch (IOException e) {  
  20.             logger.severe("请检查地址和端口是否正确......");  
  21.               
  22.             StringBuilder sb = new StringBuilder();  
  23.             sb.append(e.toString()).append("\n");  
  24.             for(StackTraceElement elem : e.getStackTrace())  
  25.             {  
  26.                 sb.append("\tat ").append(elem).append("\n");  
  27.             }  
  28.             logger.severe(sb.toString());  
  29.         }  
  30.     }  
  31.   
  32.     public static void main(String args[]) {  
  33.         new SocketHandlerTest("localhost"8080);  
  34.     }  
  35. }  


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

 

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

 

再来一个 MemoryHanlder 的例子: 
Java代码   收藏代码
  1. package my.logger;  
  2.   
  3. import java.util.logging.ConsoleHandler;  
  4. import java.util.logging.Level;  
  5. import java.util.logging.LogRecord;  
  6. import java.util.logging.Logger;  
  7. import java.util.logging.MemoryHandler;  
  8.   
  9. public class MemoryHandlerTest {  
  10.     public static void main(String[] args) {  
  11.         Logger logger = Logger.getLogger("my.logger.MemoryHandlerTest");  
  12.         ConsoleHandler handler = new ConsoleHandler();  
  13.         MemoryHandler mHandler = new MemoryHandler(handler, 10, Level.ALL);  
  14.         logger.addHandler(mHandler);  
  15.         logger.setUseParentHandlers(false);  
  16.         LogRecord record1 = new LogRecord(Level.SEVERE, "This is SEVERE level message");  
  17.         LogRecord record2 = new LogRecord(Level.WARNING, "This is WARNING level message");  
  18.         logger.log(record1);  
  19.         logger.log(record2);  
  20.   
  21.     }  
  22.   
  23. }  


(五) 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). 
Java代码   收藏代码
  1. /** 
  2.      * Reinitialize the logging properties and reread the logging configuration 
  3.      * from the given stream, which should be in java.util.Properties format. 
  4.      * A PropertyChangeEvent will be fired after the properties are read. 
  5.      * <p> 
  6.      * Any log level definitions in the new configuration file will be  
  7.      * applied using Logger.setLevel(), if the target Logger exists. 
  8.      *  
  9.      * @param ins   stream to read properties from 
  10.      * @exception  SecurityException  if a security manager exists and if 
  11.      *             the caller does not have LoggingPermission("control"). 
  12.      * @exception  IOException if there are problems reading from the stream. 
  13.      */  
  14.     public void readConfiguration(InputStream ins) throws IOException, SecurityException {  
  15.     checkAccess();  
  16.     reset();  
  17.   
  18.     // Load the properties  
  19.     props.load(ins);  
  20.     // Instantiate new configuration objects.  
  21.     String names[] = parseClassNames("config");  
  22.   
  23.     for (int i = 0; i < names.length; i++) {  
  24.         String word = names[i];  
  25.         try {  
  26.         Class clz = ClassLoader.getSystemClassLoader().loadClass(word);  
  27.         clz.newInstance();  
  28.         } catch (Exception ex) {  
  29.         System.err.println("Can't load config class \"" + word + "\"");  
  30.         System.err.println("" + ex);  
  31.         // ex.printStackTrace();  
  32.         }  
  33.     }  
  34.   
  35.     // Set levels on any pre-existing loggers, based on the new properties.  
  36.     setLevelsOnExistingLoggers();  
  37.   
  38.     // Notify any interested parties that our properties have changed.  
  39.     changes.firePropertyChange(nullnullnull);  
  40.   
  41.     // Note that we need to reinitialize global handles when   
  42.     // they are first referenced.  
  43.     synchronized (this) {  
  44.         initializedGlobalHandlers = false;  
  45.     }  
  46.     }  


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

(六)如何使用JDK内置logger  

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

我们可以自己写一个简单的JDK内置Logger使用的实用类: 
Java代码   收藏代码
  1. package my.logger;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.text.SimpleDateFormat;  
  6. import java.util.Date;  
  7. import java.util.logging.FileHandler;  
  8. import java.util.logging.Level;  
  9. import java.util.logging.Logger;  
  10. import java.util.logging.SimpleFormatter;  
  11.   
  12. public class MyLoggerUtil {  
  13.   
  14.     private static final SimpleDateFormat sdf = new SimpleDateFormat(  
  15.             "yyyy-MM-dd");  
  16.   
  17.     private static final String LOG_FOLDER_NAME = "MyLoggerFile";  
  18.   
  19.     private static final String LOG_FILE_SUFFIX = ".log";  
  20.   
  21.     private synchronized static String getLogFilePath() {  
  22.         StringBuffer logFilePath = new StringBuffer();  
  23.         logFilePath.append(System.getProperty("user.home"));  
  24.         logFilePath.append(File.separatorChar);  
  25.         logFilePath.append(LOG_FOLDER_NAME);  
  26.   
  27.         File file = new File(logFilePath.toString());  
  28.         if (!file.exists())  
  29.             file.mkdir();  
  30.   
  31.         logFilePath.append(File.separatorChar);  
  32.         logFilePath.append(sdf.format(new Date()));  
  33.         logFilePath.append(LOG_FILE_SUFFIX);  
  34.   
  35.         return logFilePath.toString();  
  36.     }  
  37.   
  38.     public synchronized static Logger setLoggerHanlder(Logger logger) {  
  39.         return setLoggerHanlder(logger, Level.ALL);  
  40.     }  
  41.   
  42.     public synchronized static Logger setLoggerHanlder(Logger logger,  
  43.             Level level) {  
  44.   
  45.         FileHandler fileHandler = null;  
  46.         try {  
  47.             //文件日志内容标记为可追加  
  48.             fileHandler = new FileHandler(getLogFilePath(), true);  
  49.   
  50.             //以文本的形式输出  
  51.             fileHandler.setFormatter(new SimpleFormatter());  
  52.               
  53.             logger.addHandler(fileHandler);  
  54.             logger.setLevel(level);  
  55.   
  56.               
  57.   
  58.         } catch (SecurityException e) {  
  59.             logger.severe(populateExceptionStackTrace(e));  
  60.         } catch (IOException e) {  
  61.             logger.severe(populateExceptionStackTrace(e));  
  62.         }  
  63.         return logger;  
  64.     }  
  65.   
  66.     private synchronized static String populateExceptionStackTrace(Exception e) {  
  67.         StringBuilder sb = new StringBuilder();  
  68.         sb.append(e.toString()).append("\n");  
  69.         for (StackTraceElement elem : e.getStackTrace()) {  
  70.             sb.append("\tat ").append(elem).append("\n");  
  71.         }  
  72.         return sb.toString();  
  73.     }  
  74. }  


使用起来也是很方便的。 

package my.logger; 

Java代码   收藏代码
  1. import java.util.logging.Logger;  
  2.   
  3. public class JDKLoggerExample {  
  4.   
  5.       
  6.     private static Logger logger = MyLoggerUtil.setLoggerHanlder(Logger.getLogger("my.logger"));  
  7.   
  8.      public static void main(String[] args) {  
  9.            
  10.          logger.info("JDK Logger is logging information at INFO Level");   
  11.     }  
  12. }  


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


 


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

然后在需要记录日志信息的地方调用logger相应的方法来完成日志信息记录即可。 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值