论坛首页 Java企业应用论坛

《How Tomcat Works》翻译(5)之 日志续集

浏览 1288 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-12-07   最后修改:2010-12-07

七、The FileLogger类

 

The FileLogger类是LoggerBase的子类,该子类是功能最为全面的类。该类一旦接收到与容器关联的消息时它就会把该消息写到一个文件中,并且 每条消息都会有任意的时间标记。当第一次实例该类时,这个类就会创建一个文件(文件名字就是创建文件的时间)。如果时间改变了,你将会创建一个新的文件并把任何消息都写到该文件(文件名字就是创建的时间)中。这个类的实例允许你在文件的名字添加一个前缀和后缀名。

 

 在Tomcat4 中FileLogger类实现了Lifecycle接口,这样就十分的方便像其他组件(都实现了org.apache.catalina.Lifecycle接口)那样,能够启动和关闭。在Tomcat 5 中却是The LoggerBase类(它是FileLogger的父类)且实现了Lifecycle接口.

 

   但是在Tomcat 4 中the LoggerBase类没有实现了Lifecycle接口,所有就没有开始启动组件。这种功能却在子类FileLogger中实现了The Lifecycle接口,因此就能够启动和关闭组件,并能够触发监听者感兴趣的事件。这两个方法会在下面代码中呈现。注意The stop方法也调用了私有close方法( 关闭文件)。The close方法将会在后面的部分讨论。

 

    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();

    }
 

   The FileLogger类最重要的方法是the log方法,请看下面的代码:

 

    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);
            }
        }

    }

 

The log方法接收到一个消息就把它写到一个日志文件里。在FileLogger实例的生命周期里,the log方法中的可能打开和关闭多个日志文件。如果日期改变,The log方法就会关闭当前的日志文件并且打开了一个新创建的一个日志文件。现在让我们来看看the log方法中的open, close 方法是怎样工作的。

 

八、The open方法

 

The open方法请看下面的代码,他主要是在制定的目录下创建一个日志文件。

    /**
     * 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;
        }

    }

 The open方法开始就核实一下目录(创建日志文件)是否存在。如果目录不存在,该方法也会创建一个目录,然后该目录就会存储到类的成员变量中。

 

      File dir=new File(directory);

      if(!dir.isAbsolute())

             dir=new File(System.getProperty("catalina.base"),directory);

     dir.mkdirs();

然后,the pathname它是由一下部分组成:一个基于打开日志文件的目录, 前缀,当前日期,后缀。

 

    try{

             String pathname=dir.getAbsolutePath()+File.separator+

                   prefix+date+suffix;

接下来,该方法有构造了一个java.io.PrintWriter类实例(该类的构造函数参数是java.io.FileWriter对象(把pathname传给该对象)),The PrintWriter实例赋给了类成员变量writer. The Log方法使用writer写日志消息。

 

          writer=new PrintWriter(new FileWriter(pathname,true),true);

 

九、The Close方法

 

The close方法清洗The PrinterWriter对象writer,清洗该对象的内容,关闭the PrinterWriter,设置The PrinterWriter为null,设置日期为空字符串。下面是the close方法代码:

 

    private void close() {

        if (writer == null)
            return;
        writer.flush();
        writer.close();
        writer = null;
        date = "";

    }
 

十、The Log方法

 

 The log方法开始是通过创建一个java.sql.Timestamp类实例(继承了java.util.Date类)。在该方法中实例化The Timestamp类的目的的是能够非常容易的获得当前的时间,并且该方法构造的Timestamp类实例时,是把当前的时间作为参数传给构造函数。

 

         Timestamp ts=new Timestamp(System.currentTimeMills());

 

使用The Timestamp类用了toString方法变成字符串,那你就能够得到当前日期的字符串形式。toString方法输出字符串格式是:  

                             yyy-mm-dd hh:mm:SS.fffffffff

这个fffffffff代表十亿分之秒。为了仅仅得到时间和小时,该方法有调用了subString方法截取字符串:

 

     String tsString=ts.toString().subString(0,19);

对于tsString字符串为了之得到日期部分那么the Log方法还需要调用subString方法:

 

    String tsDate=tsString.subString(0,10);

 

The log方法就会用tsDate与String变量的值(初始化的时候只是一个空字符串)进行比较,如果他们不一样的话,那么就会关闭当前文件,把tsDate值赋给date,打开一个新的日志文件。

 

 

 // If the date has changed, switch log files
        if (!date.equals(tsDate)) {
            synchronized (this) {
                if (!date.equals(tsDate)) {
                    close();
                    date = tsDate;
                    open();
                }
            }
        }
 

注解: 这中凡是也值得我们学习,如何打开文件,如何创建文件的名字等等,这样设计的思想就一个好字了得。。。

 

最后,the Log方法同时也写入到输出流的the PrintWriter实例。如果布尔值timestamp值是true,那么日志消息就会带有前缀(tsString),否则的会该日志消息就没有前缀。

 

 

 // Log this message, timestamped if necessary
        if (writer != null) {
            if (timestamp) {
                writer.println(tsString + " " + msg);
            } else {
                writer.println(msg);
            }
        }
 

十一、应用程序

 

本章的应用程序与第六章的应用程序十分的类似,除了你有一个FileLogger与SimpleContext对象相关联。在第六章中改变的代码将会在ex07.pyrmont.startup.Bootstrap类主方法找到。下面就请您看看代码吧。这里需要特别关注的是你看看这些变了颜色的代码就可以了。。。

 // Log this message, timestamped if necessary
        if (writer != null) {
            if (timestamp) {
                writer.println(tsString + " " + msg);
            } else {
                writer.println(msg);
            }
        }

 

十二、总结

 

  在这章你已经学到了关于the Logger组件,复习了the org.apache.catalina.Logger接口。除此之外,本章的应用程序还应用了FileLogger类,这个在Tomcat中是十分高级的logger.

 

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics