Logger是一个用来记录消息的tomcat组件并和一个container绑定在一起。
看一下它的接口定义:
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 log(String message);
public void log(Exception exception, String msg);
public void log(String message, Throwable throwable);
//当传入的日志级别verbosity大于Logger被设置的级别时,message会被记录,否则被忽略。
public void log(String message, int verbosity);
public void log(String message, Throwable throwable, int verbosity);
//属性改变监听器
public void addPropertyChangeListener(PropertyChangeListener listener);
public void removePropertyChangeListener(PropertyChangeListener listener);
}
Tomcat提供了三个Logger:FileLogger,SystemErrLogger,SystemOutLogger.
它们都继承了org.apache.catalina.logger.LoggerBase类.
在1.4中LoggerBase实现了org.apache.catalina.Logger接口.在1.5中还实现了Lifecycle接口.
![](https://i-blog.csdnimg.cn/blog_migrate/7649a47347482d6d12ab13136aef8004.png)
LoggerBase是一个抽象类, 实现了Logger接口中除了log(String msg)外的所有方法。
public abstract class LoggerBase implements Logger {
protected Container container = null;
protected int debug = 0;
//看起来是不是很熟悉?
protected static final String info ="org.apache.catalina.logger.LoggerBase/1.0";
protected PropertyChangeSupport support = new PropertyChangeSupport(this);
//默认级别
protected int verbosity = ERROR;
public Container getContainer() {
return (container);
}
public void setContainer(Container container) {
Container oldContainer = this.container;
this.container = container;
support.firePropertyChange("container", oldContainer, this.container);
}
public void setVerbosityLevel(String verbosity) {
if ("FATAL".equalsIgnoreCase(verbosity))
this.verbosity = FATAL;
else if ("ERROR".equalsIgnoreCase(verbosity))
this.verbosity = ERROR;
else if ("WARNING".equalsIgnoreCase(verbosity))
this.verbosity = WARNING;
else if ("INFORMATION".equalsIgnoreCase(verbosity))
this.verbosity = INFORMATION;
else if ("DEBUG".equalsIgnoreCase(verbosity))
this.verbosity = DEBUG;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(listener);
}
public abstract void log(String msg);
public void log(Exception exception, String msg) {
log(msg, exception);
}
public void log(String msg, Throwable throwable) {
CharArrayWriter buf = new CharArrayWriter();
PrintWriter writer = new PrintWriter(buf);
writer.println(msg);
throwable.printStackTrace(writer);
Throwable rootCause = null;
if (throwable instanceof LifecycleException)
rootCause = ((LifecycleException) throwable).getThrowable();
else if (throwable instanceof ServletException)
rootCause = ((ServletException) throwable).getRootCause();
if (rootCause != null) {
writer.println("----- Root Cause -----");
rootCause.printStackTrace(writer);
}
log(buf.toString());
}
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);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
support.removePropertyChangeListener(listener);
}
......
}
SystemErrLogger,SystemOutLogger继承了LoggerBase,实现如其名,超级简单。
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);
}
}
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);
}
}
FileLogger相比上面两个复杂一些。它把从容器中接到的消息写到一个文件中。文件名和日期相关,当日期改变时,它会新建一个文件。
在1.4中FileLogger实现了Lifecycle接口,它可以像其他实现了Lifecycle接口的组件一样被启动/停止。
在1.5中 FileLogger的父类LoggerBase实现了 Lifecycle 接口。
public void start() throws LifecycleException {
if (started)
throw new LifecycleException (sm.getString("fileLogger.alreadyStarted"));
lifecycle.fireLifecycleEvent(START_EVENT, null); started = true;
}
public void stop() throws LifecycleException {
if (!started)
throw new LifecycleException (sm.getString("fileLogger.notStarted"));
lifecycle.fireLifecycleEvent(STOP__EVENT, null);
started = false;
close ();
}
public void log(String msg) {
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
String tsDate = tsString.substring(0, 10);
//当日期改变时,创建被切换日志文件
if (!date.equals(tsDate)) {
synchronized (this) {
if (!date.equals(tsDate)) {
close();
date = tsDate;
//在指定的目录中创建一个新文件
open();
}
}
}
//记录消息,并附上时间
if (writer != null) {
if (timestamp) {
writer.println(tsString + " " + msg);
} else {
writer.println(msg);
}
}
}
//在指定目录中创建一个新文件
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;
}
}
private void close() {
if (writer == null) return;
writer.flush();
writer.close();
writer = null;
date = "";
}