前幾天用到了一次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()的時候,裏面的具體實現是這樣的。
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