記錄一個java.util.logging.Logger 使用中關於時間格式的問題

前幾天用到了一次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控制檯打印的日誌格式。


修改完屬性文件重新運行程序,此時控制檯中打印的日誌格式如下:



此時就是我當時想要的時間格式了。


關於Java的格式化輸出問題(和時間相關的)可以看下百度的這篇文章:(Java格式化輸出
)http://wenku.baidu.com/link?url=_R6-BPLU22QOkyW56wAflHwOcS4ZGWP8Dr-85203iobs0lBC-zDfXxKsCNIkOywbRwnKo9dgD2R5lzcKX3lXcv2clv49iKIaWRnWmmLNlNe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章