大家可以松一口氣了,這個元件比較簡單,這一節和前面幾節想比,也簡單的多。
Logger接口
Tomcat中的日志記錄器都必須實作org.apache.catalina.Logger接口。
package org.apache.catalina;
import java.beans.PropertyChangeListener;
public interface Logger {
public static final int FATAL = Integer.MIN_VALUE;
public static final int ERROR = 1;
public static final int WARNING = 2;
public static final int INFORMATION = 3;
public static final int DEBUG = 4;
public Container getContainer();
public void setContainer(Container container);
public String getInfo();
public int getVerbosity();
public void setVerbosity(int verbosity);
public void addPropertyChangeListener(PropertyChangeListener listener);
public void log(String message);
public void log(Exception exception, String msg);
public void log(String message, Throwable throwable);
public void log(String message, int verbosity);
public void log(String message, Throwable throwable, int verbosity);
public void removePropertyChangeListener(PropertyChangeListener listener);
}
Logger定義了五種日志記錄基本,當我們在調用log(String message, int verbosity)方法記錄日志的時候,隻有傳進來的verbosity小于等于系統的預設值才會記錄。話說大家知道Integer.MIN_VALUE等于多少嗎?大概負的21億左右吧。setVerbosity與getVerbosity是幹什麼的還需要我說麼?
Tomcat的日志記錄器
LoggerBase類(抽象類)
它實作了Logger接口中除log(String message)方法外的其餘方法;
在類中預設了日志記錄級别為
protected int verbosity = ERROR;
但是我們可以通過setVerbosity(int verbosity)來重新設定記錄級别;
看看定義的接受日志級别的兩個log方法
public void log(String message, int verbosity) {
if (this.verbosity >= verbosity)
log(message);
}
public void log(String message, Throwable throwable, int verbosity) {
if (this.verbosity >= verbosity)
log(message, throwable);
}
SystemOutLogger類
看名字就知道,資訊最後輸出到控制台。
SysteErrLogger類
看名字就知道,它是錯誤輸出,資訊仍在控制台,不過是紅色的。
FileLogger類
看名字就知道,它是吧資訊輸出的檔案裡。
不過具體的來說,裡面還是有點說頭的,慢慢來。
首先FileLogger還實作了Lifecycle接口,是以它可以像其他元件一樣被父元件所啟動。
在本節中FileLogger的start與stop方法其實隻是改變了布爾值started而已,沒有做其他的,另一方面,FileLogger的start與stop方法也并沒有被調用!
現在我們就看看怎麼給檔案裡寫資訊。
public void log(String msg) {
// Construct the timestamp we will use, if requested
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
String tsDate = tsString.substring(0, 10);
System.out.println("tsString "+tsString); //tsString 2014-10-20 15:25:27
System.out.println("ts "+ts); //ts 2014-10-20 15:25:27.406
System.out.println("tsDate "+tsDate); //tsDate 2014-10-20
// If the date has changed, switch log files
if (!date.equals(tsDate)) {
synchronized (this) {
if (!date.equals(tsDate)) {
close();
date = tsDate;
open();
}
}
}
// Log this message, timestamped if necessary
if (writer != null) {
if (timestamp) {
writer.println(tsString + " " + msg);
} else {
writer.println(msg);
}
}
}
File預設是每一天一個新的檔案,檔案内格式就是日期+具體資訊(如果timestamp為true的話);
那close(),open()方法和writer屬性又是什麼呢?
private void open() {
// Create the directory if necessary
File dir = new File(directory);
if (!dir.isAbsolute())
dir = new File(System.getProperty("catalina.base"), directory); //至于catalina.base是什麼 一會再說
dir.mkdirs();
// Open the current log file
try {
String pathname = dir.getAbsolutePath() + File.separator +
prefix + date + suffix;
writer = new PrintWriter(new FileWriter(pathname, true), true);
} catch (IOException e) {
writer = null;
}
}
先檢查給定的目錄是否存在,如果不存在建立一個;接着根據字首,時間,字尾設定檔案名;根據檔案名填充writer對象。
private void close() {
if (writer == null)
return;
writer.flush();
writer.close();
writer = null;
date = "";
}
FileLogger中的date代表的就是目前的時間,當然關閉後為空。
應用程式
Bootstrap類
...
System.setProperty("catalina.base", System.getProperty("user.dir"));
FileLogger logger = new FileLogger();
logger.setPrefix("FileLog_");
logger.setSuffix(".txt");
logger.setTimestamp(true);
logger.setDirectory("webroot");
context.setLogger(logger);
....
SimpleContext類
public synchronized void start() throws LifecycleException {
log("starting Context");
........
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
log("Context started");
}
private void log(String message) {
Logger logger = this.getLogger();
if (logger!=null)
logger.log(message);
}
運作後在項目的webroot目錄下就可以看到FileLog_2014-10-20.txt檔案;
每次運作,在檔案中都會多出如下的内容
2014-10-20 14:34:21 HttpConnector Opening server socket on all host IP addresses
2014-10-20 14:34:22 HttpConnector[8080] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][0] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][1] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][2] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][3] Starting background thread
2014-10-20 14:34:22 HttpProcessor[8080][4] Starting background thread
2014-10-20 14:34:22 starting Context