本文接下来分析tomcat的日志记录器,日志记录器是用来记录消息的组件,在tomcat中,日志记录器需要与某个servlet容器相关连;在org.apache.catalina.logger包下,tomcat提供了几种不同类型的日志记录器。
tomcat中的日志记录器都必须实现org.apache.catalina.Logger接口
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); }
通常,当传入的日志级别verbosity大于Logger被设置的级别时,message会被记录,否则被忽略
Logger接口共定义了五种日志级别,分别为FATAL ERROR WARNING INFORMATION DEBUG
Tomcat提供了三种类型的日志记录器,分别为SystemOutLogger、SystemErrLogger、FileLogger,在org.apache.catalina.logger包下,均继承自org.apache.catalina.logger.LoggerBase类
LoggerBase类实现了org.apache.catalina.Logger接口,在tomcat5中还实现了Lifecycle接口
LoggerBase类为抽象类,实现了Logger接口中除abstract void log(String msg)外的全部方法实现,所有的其他重载方法最终都会调用该方法(templet模式),我们还可以调用setVerbosity()方法设置日志级别
具体日志类都比较简单,下面是SystemOutLogger类的实现
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); } }
SystemErrLogger类
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类稍微复杂一点,将从servlet容器中接收到的消息写入到一个文件中(在tomcat4中,FileLogger类实现了Lifecycle接口)
public class FileLogger extends LoggerBase implements Lifecycle { protected LifecycleSupport lifecycle = new LifecycleSupport( this ); private StringManager sm = StringManager.getManager(Constants.Package); private boolean started = false ; private String suffix = ".log" ; private boolean timestamp = false ; private PrintWriter writer = null ; 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 ); // 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); } } } private void close() { if (writer == null ) return ; writer.flush(); writer.close(); writer = null ; date = "" ; } /** * Open the new log file for the date specified by <code>date</code>. */ private void open() { // Create the directory if necessary File dir = new File(directory); if (! dir.isAbsolute()) dir = new File(System.getProperty("catalina.base" ), directory); 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 ; } } public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); }
public LifecycleListener[] findLifecycleListeners() { return lifecycle.findLifecycleListeners(); } public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } public void start() throws LifecycleException { // Validate and update our current component state if (started) throw new LifecycleException (sm.getString( "fileLogger.alreadyStarted" )); lifecycle.fireLifecycleEvent(START_EVENT, null ); started = true ; } public void stop() throws LifecycleException { // Validate and update our current component state if (! started) throw new LifecycleException (sm.getString( "fileLogger.notStarted" )); lifecycle.fireLifecycleEvent(STOP_EVENT, null ); started = false ; close(); } }
---------------------------------------------------------------------------
本系列How Tomcat Works系本人原创
转载请注明出处 博客园 刺猬的温驯
本人邮箱: chenying998179 # 163.com ( #改为@ )