日志记录器是一个组件,必须和某个servlet容器关联才能使用。
package org.apache.catalina;
import java.beans.PropertyChangeListener;
public interface Logger {
//日志记录器可以记录5种类型的日志,用int型整数表示等级,
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);
//有5种记录日志的方式
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);
}
Tomcat4种日志记录器的UML图:
LoggerBase是一个抽象类,实现了Logger接口除public void log(String message);以外的全部方法,因此,需要其子类实现抽象方法public abstract void log(String msg)。
SystemOutLogger、SystemErrorLogger、FileLogger3个类都由Tmocat提供。
1、SystemOutLogger类
package org.apache.catalina.logger;
public class SystemOutLogger
extends LoggerBase {
protected static final String info =
"org.apache.catalina.logger.SystemOutLogger/1.0";
public void log(String msg) {
System.out.println(msg);//将每条日志消息传递给System.out.println(),并输出
}
}
2、SystemErrLogger
package org.apache.catalina.logger;
public class SystemErrLogger
extends LoggerBase {
protected static final String info =
"org.apache.catalina.logger.SystemErrLogger/1.0";
public void log(String msg) {
System.err.println(msg);//将日志信息输出到标准错误
}
}
3、FileLogger类(代码太长就不贴出来了)
FileLogger类中几个比较重要的方法:
public void log(String msg) {
Timestamp ts = new Timestamp(System.currentTimeMillis());//获取当前系统时间,并把该时间作为时间戳保存到变量ts中,Timestamp是java.util.Date的廋包装
String tsString = ts.toString().substring(0, 19);
String tsDate = tsString.substring(0, 10);
if (!date.equals(tsDate)) {//首次执行程序时,date=""
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);//有时间戳,使用PrintWriter写入日志
} else {
writer.println(msg);//无时间戳,使用PrintWriter写入日志
}
}
}
private void open() {
File dir = new File(directory);
if (!dir.isAbsolute())
dir = new File(System.getProperty("catalina.base"), directory);
dir.mkdirs();
try {
String pathname = dir.getAbsolutePath() + File.separator +
prefix + date + suffix;
writer = new PrintWriter(new FileWriter(pathname, true), true);
} catch (IOException e) {
writer = null;
}
}
程序执行过程:
// ------ add logger --------
System.setProperty("catalina.base", System.getProperty("user.dir"));
FileLogger logger = new FileLogger();//新建一个FileLogger实例
logger.setPrefix("FileLog_");
logger.setSuffix(".txt");
logger.setTimestamp(true);
logger.setDirectory("WebRoot");
context.setLogger(logger);//并将这个实例和容器关联
public synchronized void start() throws LifecycleException {
log("starting Context");//容器启动时,调用log(String message) 方法,添加日志
if (started)
throw new LifecycleException("SimpleContext has already started");
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
try {
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
lifecycle.fireLifecycleEvent(START_EVENT, null);
}
catch (Exception e) {
e.printStackTrace();
}
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
log("Context started");
}
private void log(String message) {
Logger logger = this.getLogger();
if (logger!=null)
logger.log(message);//调用和容器关联的日志记录器的log(String message)方法,将日志写入指定文件中
}