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

记录一个java.util.logging.Logger 使用中关于时间格式的问题

2016-06-22 13:15 856 查看
前几天用到了一次java.util.logging.Logger类,该类可以打印相关日志信息并将日志信息写入日志文件。初学该类的时候,代码是从网上拷贝的,具体内容如下:

p

package com.wlh.util;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

public class TestLogger {

    private static Logger logger = Logger.getLogger(TestLogger.class.getName());
    static {
        try {
            FileHandler fileHandler = null;

            fileHandler = new FileHandler("D:\\log_" + System.currentTimeMillis() + ".log");

            final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            fileHandler.setFormatter(new Formatter() {
                @Override
                public synchronized String format(LogRecord record) {
                    String dateFormat = sdf.format(record.getMillis());
                    String source;
                    if (record.getSourceClassName() != null) {
                        source = record.getSourceClassName();
                        if (record.getSourceMethodName() != null) {
                            source += " " + record.getSourceMethodName();
                        }
                    } else {
                        source = record.getLoggerName();
                    }
                    String message = formatMessage(record);
                    String throwable = "";
                    if (record.getThrown() != null) {
                        StringWriter sw = new StringWriter();
                        PrintWriter pw = new PrintWriter(sw);
                        pw.println();
                        record.getThrown().printStackTrace(pw);
                        pw.close();
                        throwable = sw.toString();
                    }
                    StringBuilder sb = new StringBuilder();
                    sb = sb.append(dateFormat).append("  ").append("class:").append(source).append(" ").append(record.getLoggerName()).append(" ")
                            .append(record.getLevel().getLocalizedName()).append(" ").append(record.getMessage())
                            .append(" ").append(throwable).append("\r\n");
                    return String.format("%-8s", sb.toString());
                }
            });
            logger.addHandler(fileHandler);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void showWarning(String message) {
        logger.log(Level.WARNING, message);
    }

    public static void showInfo(String message) {
        logger.info(message);
    }

    public static void main(String[] args) {
        WebLogger.showInfo("Hello World");
        WebLogger.showWarning("Hello Warning");
    }
}



此时执行后便会在java的控制台中显示如下格式的信息:



看着上图的实际格式,我有些不爽啊。我还是喜欢 “yyyy-MM-dd HH:mm:ss”这样的时间格式啊。那就修改格式吧,通过跟踪代码,发现了其中的奥秘,也知道了要修改那里。

在 new FileHandler()的时候,里面的具体实现是这样的。

 public FileHandler() throws IOException, SecurityException {

        checkPermission();

        configure();

        openFiles();
    }

这里有个configure()方法,该方法的第一句是LogManager manager = LogManager.getLogManager();

此时我们到getLogManager()方法里去看看它都做了哪些事情:

/**
* Return the global LogManager object.
*/
public static LogManager getLogManager() {
if (manager != null) {
manager.readPrimordialConfiguration();
}
return manager;
}

所有我们接下来去看readPrimordialConfiguration() 方法做什么?

private void readPrimordialConfiguration() {
if (!readPrimordialConfiguration) {
synchronized (this) {
if (!readPrimordialConfiguration) {
// If System.in/out/err are null, it's a good
// indication that we're still in the
// bootstrapping phase
if (System.out == null) {
return;
}
readPrimordialConfiguration = true;

try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
public Void run() throws Exception {
<span style="color:#FF0000;">readConfiguration();</span>//这个方法是最关键的地方

// Platform loggers begin to delegate to java.util.logging.Logger
sun.util.logging.PlatformLogger.redirectPlatformLoggers();
return null;
}
});
} catch (Exception ex) {
// System.err.println("Can't read logging configuration:");
// ex.printStackTrace();
}
}
}
}
}

在readConfiguration()方法中会去读取相关的属性文件【logging.properties】,该属性文件存在于你的java_home下的 /jre/lib文件夹下,然后你可以修改其中的相关配置
/**
* Reinitialize the logging properties and reread the logging configuration.
* <p>
* The same rules are used for locating the configuration properties
* as are used at startup. So normally the logging properties will
* be re-read from the same file that was used at startup.
* <P>
* Any log level definitions in the new configuration file will be
* applied using Logger.setLevel(), if the target Logger exists.
* <p>
* A PropertyChangeEvent will be fired after the properties are read.
*
* @exception SecurityException if a security manager exists and if
* the caller does not have LoggingPermission("control").
* @exception IOException if there are IO problems reading the configuration.
*/
public void readConfiguration() throws IOException, SecurityException {
checkPermission();

// if a configuration class is specified, load it and use it.
String cname = System.getProperty("java.util.logging.config.class");
if (cname != null) {
try {
// Instantiate the named class. It is its constructor's
// responsibility to initialize the logging configuration, by
// calling readConfiguration(InputStream) with a suitable stream.
try {
Class clz = ClassLoader.getSystemClassLoader().loadClass(cname);
clz.newInstance();
return;
} catch (ClassNotFoundException ex) {
Class clz = Thread.currentThread().getContextClassLoader().loadClass(cname);
clz.newInstance();
return;
}
} catch (Exception ex) {
System.err.println("Logging configuration class \"" + cname + "\" failed");
System.err.println("" + ex);
// keep going and useful config file.
}
}

String fname = System.getProperty("java.util.logging.config.file");
if (fname == null) {
fname = System.getProperty("java.home");
if (fname == null) {
throw new Error("Can't find java.home ??");
}
File f = new File(fname, "lib");
f = new File(f, "logging.properties");
fname = f.getCanonicalPath();
}
InputStream in = new FileInputStream(fname);
BufferedInputStream bin = new BufferedInputStream(in);
try {
readConfiguration(bin);
} finally {
if (in != null) {
in.close();
}
}
}

我将属性文件的内容中加了一句话,就能出现我想要的日志格式了。具体在【logging.properties】中加入的内容如下图:



插入的内容就是:  java.util.logging.SimpleFormatter.format=%1$tF %1$tH:%1$tM:%1$tS %2$s%n%4$s: %5$s%6$s%n

说明:此时如果没有这句话,那默认使用的SimpleFormatter的format格式是:"%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%6$s%n"; 这个格式就是刚才我们在上面的图片中看到

的eclipse控制台打印的日志格式。

[b]修改完属性文件重新运行程序,此时控制台中打印的日志格式如下:
[/b]



此时就是我当时想要的时间格式了。

关于Java的格式化输出问题(和时间相关的)可以看下百度的这篇文章:(Java格式化输出

)http://wenku.baidu.com/link?url=_R6-BPLU22QOkyW56wAflHwOcS4ZGWP8Dr-85203iobs0lBC-zDfXxKsCNIkOywbRwnKo9dgD2R5lzcKX3lXcv2clv49iKIaWRnWmmLNlNe
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: