`
dicmo
  • 浏览: 68523 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Coder 爱翻译 How Tomcat Works 第七章

    博客分类:
  • j2ee
阅读更多
Chapter 7: Logger

日志是一个记录信息的组件。在Catalina中,它容器相关联的日志比其它组件相对简单得多。Tomcat在org.apache.catalina.logger包下提供多种类型的日志。
本章有三个部分:第一部分包括org.apache.catalina.Logger接口,所有的日志组件都必须实现这个接口。第二部分介绍了在Tomcat中的日志,第三章详细讲述了本章的应用程序使用Tomcat的日志。

The Logger Interface

一个日志必须实现org.apache.catalina.Logger接口:
Listing 7.1: The Logger interface   
 
package org.apache.catalina; 
import java.beans.PropertyChangeListener; 
 
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); 
} 

Logger接口提供许多log方法供实现类选择调用。这些方法中最简单的方法是接受一个字符串,这个字符串被用来当做记录信息。

最后两个log方法接收一个详细记录级别。如果传递的这个数比这个类实例设置的详细记录级别低,这个信息就会被记录下来。否则,这个信息会被忽略。这里用public Static变量定义了5个详细记录级别:FATAL, ERROR, WARNING, INFORMATION和DEBUG。而getVerbosity和setVerbosity方法用来获取和设置相应的值。

此外,Logger接口有getContainer和setContainer方法把一个Logger实例和一个容器相关联起来。它也提供addPropertyChangeListener和removePropertyChangeListener方法,来增加和移除一个PropertyChangeListener。

当你看见在Tomcat中的logger类的实现,这些方法将会更清楚,容易理解。

Tomcat's Loggers

Tomcat提供三个日志记录类:FileLogger, SystemErrLogger和SystemOutLogger。这些类都在org.apache.catalina.logger包下面,且它们都继承自org.apache.catalina.logger.LoggerBase类。在Tomcat 4中,LoggerBase类实现了org.apache.catalina.Logger接口。在Tomcat 5中,它也实现了Lifecycle和MbeanRegistration。类图:



The LoggerBase Class

在Tomcat 5中,LoggerBase类相当复杂,因为它包含了创建MBeans的代码。这里我们看Tomcat 4中的LoggerBase类。

在Tomcat 4中,LoggerBase类是一个抽象类,它提供Logger接口的所有方法实现,除了
log(String msg)方法。
public abstract void log(String msg);

这个方法重载是在子类中记录信息。而其他所有的log方法重载都调用这个重载。因为每一个子类把记录信息记录到不同的地方,所以这个在LoggerBase类的方法重载为空。

现在看看这个类的详细记录等级。它通过一个protected的叫做verbosity的变量来定义的。ERROR是它的默认值:
protected int verbosity = ERROR;

详细记录等级可以通过调用setVerbosity方法来改变等级。传递下面的字符串:FATAL, ERROR, WARNING, INFORMATION或DEBUG。

Listing 7.2: The setVerbosity method   
 
public void setVerbosityLevel(String verbosity) { 
   if ("FATAL".equalsIgnoreCase(verbosity)) 
     this.verbosity = FATAL; 
   else if ("ERROR".egualsIgnoreCase(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; 
}


有两个log方法接收一个整型作为详细记录等级。在这些方法重载中,如果传递给详细记录等级的值比实例的详细记录的等级低时,log(String message)这个方法重载会被调用。
Listing 7.3: The log method overloads that accept verbosity   
 
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); 
} 

下面我们讨论LoggerBase类的三个子类,你将看到log(String message)方法重载的实现。

The SystemOutLogger Class

LoggerBase类的子类提供了log(String message)方法重载的实现。每一个接收的message会被传递给System.out.println方法。
Listing 7.4: The SystemOutLogger Class   
 
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); 
   } 
} 


The SystemErrLogger Class

这个类和SystemOutLogger相似。除了传递给log(String message)方法的重载的message参数的调用,message会传递给System.err.println()方法。
Listing 7.5: The SystemErrLogger class   
 
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); 
   } 
} 


The FileLogger Class

FileLogger类是LoggerBase的最复杂的子类。它把接收到的信息写入一个文件。每个信息可以被标记上时间戳。当首先初始化时,这个类的实例创建一个文件,它的名字包含当天的日期信息。如果日期变化了,它将为这个新日期创建一个新的文件,然后记录下所有信息。这个类实例允许你添加一个前缀和后缀给日志文件的名字。

在Tomcat 4中。FileLogger类实现了Lifecycle接口,所以它可以被实现了org.apache.catalina.Lifecycle接口的任意组件来启动和停止它。在Tomcat 5中,LoggerBase类(FileLogger的父类)实现了Lifecycle。

在tomcat 4中LoggerBase(继承Lifecycle接口)类的start和stop方法只是触发了监听器相关的生命周期事件的启动和停止事件。注意stop方法也调用了private close方法关闭日志文件。
Listing 7.6: The start and stop methods   
 
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 (); 
} 

FileLogger类的最重要的方法是log方法。
Listing 7.7: The log method   
 
public void log(String msg) { 
   // Construct the timestamp we will use, if reguested 
   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); 
     } 
   } 
}

log方法接收一个message,并写入到日志文件。在FileLogger实例的生命周期期间,log方法可能打开和关闭多个日志文件。典型地,如果日期变化了,log方法通过关闭当前文件,并打开一个新的文件来交替日志文件。让我们看下open、close和log方法怎么工作。

The open method

open方法在制定的目录中创建一个新的log文件。
Listing 7.8: The open method   
 
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) {
   catch (IOException e) { 
     writer = null; 
   } 
} 

open方法首先检查创建日志文件的目录是否存在。如果这个目录不存在,这个方法也创建这个目录。这个目录被存储在类变量directory。
  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;

接下来,它构建一个java.io.PrintWriter实例,它的writer是一个记录了路径名的java.io.FileWriter对象。然后PrintWriter实例指配给类变量writer。log方法使用writer来记录message。
writer = new PrintWriter(new FileWriter(pathname, true), true);


The close method

close方法刷新PrintWriter的writer,刷新它的内容,关闭PrintWriter,把PrintWriter设置为null,并设置日期为一个空字符串。
Listing 7.9: The close method   
 
private void close() { 
   if (writer == null) 
     return; 
   writer.flush(); 
   writer.close(); 
   writer = null; 
   date = ""; 
} 

The log method

log方法通过创建一个java.sql.Timestamp类的实例开始。这个Timestamp类是一个java.util.Date类的轻微包装。在log方法里实例化Timestamp类的目是为了更容易获取当前日期。log方法用传递一个用long长整型表示的当前时间给Timestamp类的构造器来构建一个TimeStamp实例。
Timestamp ts = new Timestamp(System.currentTimeMillis());

使用Timestamp的toString方法,你可以获取当前日期的字符串表现形式。toString方法的输出下面格式:
yyyy-mm-dd hh:mm: SS.fffffffff

fffffffff表示从00:00:00经过的毫秒数。要获取日期和小时,log方法调用substring方法:
String tsString = ts.toString().substring(0, 19);

然后,从tsString获取日期部分,log方法使用下面方法:
String tsDate = tsString.substring(0, 10);

然后log方法比较tsDate和初始化为空字符串的String变量date,如果tsDate的值和date变量不相同,它就关闭当前日志文件,指配tsDate的值给date,打开这个新的日志文件。
   // If the date has changed, switch log files 
   if (!date.equals(tsDate)) { 
     synchronized (this) { 
       if (!date.equals(tsDate)) { 
         close(); 
         date = tsDate; 
         open(); 
       } 
     } 
   }

最后,log方法把输出流PrintWriter实例写入日志文件。如果timestamp的变量值是true,它给信息加上时间戳前缀(tsString)。否则,它记录的信息,不加时间戳前缀。
   // Log this message, timestamped if necessary 
   if (writer != null) { 
     if (timestamp) { 
       writer.println(tsString + " " + msg); 
     } else { 
       writer.println(msg); 
     } 
   }

The Application

和第六章的应用程序类似。除了你有一个SimpleContext对象相关的FileLogger。
Listing 7.10: The Bootstrap class   
 
package ex07.pyrmont.startup; 
 
import ex07.pyrmont.core.SimpleContext; 
import ex07.pyrmont.core.SimpleContextLifecycleListener; 
import ex07.pyrmont.core.SimpleContextMapper; 
import ex07.pyrmont.core.SimpleLoader; 
import ex07.pyrmont.core.SimpleWrapper; 
import org.apache.catalina.Connector; 
import org.apache.catalina.Context; 
import org.apache.catalina.Lifecycle; 
import org.apache.catalina.LifecycleListener; 
import org.apache.catalina.Loader; 
import org.apache.calalina.loggor.FileLogger; 
import org.apache.catalina.Mapper;
import org.apache.catalina.Wrapper; 
import org.apache.catalina.connector.http.HttpConnector; 
 
public final class Bootstrap { 
   public static void main(String[] args) { 
     Connector connector = new HttpConnector(); 
     Wrapper Wrapper1 = new SimpleWrapper(); 
     Wrapper1.setName("Primitive"); 
     Wrapper1.setServletClass("PrimitiveServlet"); 
     Wrapper wrapper2 = new SimpleWrapper(); 
     wrapper2.setName("Modern"); 
     Wrapper2.setServletClass("ModernServlet"); 
     Loader loader = new SimpleLoader(); 
     Context context = new SimpleContext(); 
     context.addChild(wrapper1); 
     context.addChild(wrapper2); 
 
     Mapper mapper = new SimpleContextMapper(); 
     mapper.setProtocol("http"); 
     LifecycleListener listener = new SimpleContextLifecycleListener(); 
     ((Lifecycle) context).addLifecycleListener(listener); 
     context.addMapper(mapper); 
     context.setLoader(loader); 
     // context.addServletMapping(pattern, name); 
     context.addServletMapping("/Primitive", "Primitive"); 
     context.addServletMapping("/Modern", "Modern");
// ------ add logger -------- 
     System.setProperty("catalina.base", 
System.getProperty("user.dir")); 
     FileLogger logger = new FileLogger(); 
     logger.setPrefix("FileLog_"); 
     logger.setSuffix(".txt"); 
     logger.setTimestamp(true); 
     logger.setDirectory("webroot"); 
     context.setLogger(logger); 
     //-------------------------- 
     connector.setContainer(context); 
     try { 
       connector.initialize(); 
       ((Lifecycle) connector).start(); 
       ((Lifecycle) context).start(); 
     // make the application wait until we press a key. 
       System.in.read(); 
       ((Lifecycle) context).stop(); 
     } catch (Exception e) { 
  		e.printStackTrace(); 
     } 
   } 
}


                                                                         第七章 完
  • 大小: 22.1 KB
1
0
分享到:
评论

相关推荐

    tomcat原理解析书(how-tomcat-works)中文版

    适合读者 1.jsp/servlet 开发人员,想了解 tomcat 内部机制的 coder; 2.想加入 tomcat 开发团队的 coder; 3.web 开发人员,但对软件开发很有兴趣的 coder; 4.想要对 tomcat 进行定制的 coder。

    Bad Programming Practices 101 Become a Better Coder by Learning How (Not) epub

    Bad Programming Practices 101 Become a Better Coder by Learning How (Not) to Program 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书

    phpcoder.rar

    2. 使用解压缩工具(如WinRAR或7-Zip)解压文件。 3. 在解压后的文件夹中找到可执行程序,通常命名为"PHPCoder.exe"。 4. 双击运行,按照安装向导的提示进行操作。 5. 完成安装后,可以从桌面快捷方式启动PHPCoder。...

    mediacoder专业版

    mediacoder 5685专业版,无普通版的限制

    MediaCoder答题器

    6. 插件扩展:MediaCoder有一个开放的插件架构,用户可以通过安装第三方插件来增加新的编码解码器、滤镜和其他功能,扩展其应用范围。 7. 用户友好:MediaCoder的界面简洁直观,即便是对编码不熟悉的用户也能快速...

    matlab Embedded Coder Getting Started Guide.pdf

    Embedded Coder用于产生嵌入式处理器、目标快速原型板和大规模生产中使用的微处理器的可读的、紧凑的、快速的C和C++代码。Embedded Coder支持附加的MATLAB Coder™和Simulink Coder™配置选项,以及对生成代码的功能...

    simulink hdl coder 用户手册pdf

    ### Simulink HDL Coder 用户手册概览与关键技术知识点 #### 一、Simulink HDL Coder 简介 Simulink HDL Coder 是 MathWorks 提供的一款强大的工具,它允许用户将 Simulink 模型转换为硬件描述语言(HDL)代码,...

    The Clean Coder

    Martin, "The Clean Coder: A Code of Conduct for Professional Programmers" Prentice Hall | 2011 | ISBN: 0137081073 | 256 pages | PDF | 6 MB Programmers who endure and succeed amidst swirling ...

    Mediacoder基础教程

    **Mediacoder基础教程** Mediacoder是一款强大的多媒体编码工具,专为音频和视频转换而设计,支持多种格式,如MP4、AVI、MKV等。本教程将深入讲解如何利用Mediacoder进行视频压制,优化视频质量,同时合理权衡码率...

    CoolCoder 类生成工具

    为了提高开发效率,许多开发者选择使用代码生成工具,如“CoolCoder类生成工具”。该工具专为简化实体类以及相关映射文件的创建而设计,尤其对于使用NHibernate框架的项目来说,它能够极大地提升开发速度,减少重复...

    HDL-Coder详细教程

    ### HDL-Coder详细教程知识点概述 #### 一、生成HDL代码前的准备工作 在开始从Simulink模型生成HDL代码之前,需要完成一系列的准备工作,确保模型能够顺利生成高质量的代码。 ##### 1.1 使用`hdlsetup`进行模型...

    php coder编辑器

    PHPCoder用于快速开发和调试PHP应用程序,它很容易扩展和定制,完全能够符合开发者的个性要求.PHPCoder是一个非常实用的,功能强大的编程环境,而且它是免费的!

    matlab coder基本函数教程

    ### MATLAB Coder 基本函数教程 #### MATLAB Coder 概述 MATLAB Coder 是一款能够将 MATLAB 代码转换成独立的 C 或 C++ 代码的强大工具。这一过程对于那些希望在非 MATLAB 环境下部署 MATLAB 代码的应用开发者来说...

    MediaCoder.5755专业破解版

    MediaCoder行业版一款针对VOD及KTV视频点播行业开发的,用于转换和处理带有多音轨内容的视频节目的软件。它具备业界领先的视频编码引擎,在高性能转码的同时保持高画质,并通过丰富的视频滤镜增强画面视觉效果。作为...

    MediaCoder

    MediaCoder是一款功能强大的多媒体转换工具,它支持广泛的音频和视频编码格式,使用户能够轻松地在不同设备之间转换媒体文件。这款软件适用于个人用户、专业音频和视频制作人员,以及那些希望在各种设备上享受多媒体...

    MatlabCoder使用-Matlab Coder的基本使用.pdf

    Matlab Coder是Mathworks公司推出的一款用于将Matlab代码转换成高效C代码的工具。从2004年开始,Matlab陆续在Simulink中添加了Embeded Matlab Function模块,2007年在Real-Time Workshop中引入了emlc函数(现在的...

    Embedded Coder.rar

    texasinstrumentsc2000.mlpkginstall 支持TI的C2000系列工具包,要求MATLAB R2017a及其以上版本。 安装方法:打开matlab,调整路径到mlpkginstall文件所在目录;在current folder窗口里双击mlpkginstall文件即可开始...

    AI自动生成SQL语句的开源代码 sqlcoder-main.zip

    开源的AI自动生成SQL语句源代码,这款SQLCoder-70B-Alpha在文本到SQL的转换能力上超越了包括GPT-4在内的所有通用模型,它能更准确地理解你的需求,并生成相应的SQL查询。SQLCoder2和SQLCoder-7B模型已经向公众开放,...

    MediaCoder64位专业破解版

    MediaCoder-Premium-x64 MediaCoder是最早开始使用GPU进行视频编码加速的影音转码软件之一。通过将原本完全依赖CPU的计算工作转移到GPU上进行,H.264和H.265编码所需的时间被大幅缩短。

Global site tag (gtag.js) - Google Analytics