7.1 Tomcat学习(日志记录器Logger)

日志记录器是一个组件,必须和某个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图:

7.1 Tomcat学习(日志记录器Logger)_第1张图片

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继承LoggerBase类,并且实现Lifecycle接口

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)方法,将日志写入指定文件中
  }





你可能感兴趣的:(《深入剖析Tmocat》)