Logger是一個用來記錄消息的tomcat組件並和一個container綁定在一塊兒。
看一下它的接口定義: java
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.
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,實現如其名,超級簡單。 apache
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相比上面兩個複雜一些。它把從容器中接到的消息寫到一個文件中。文件名和日期相關,當日期改變時,它會新建一個文件。
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 = ""; }