- 浏览: 27737 次
- 性别:
- 来自: 广州
最新评论
日志记录器挺简单的,没有很多东西,最主要的就是一个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); }
只要实现Logger就能有一个自己的日志记录器,其中setContainer是把日志记录器跟具体的容器关联,setVerbosity是设置日志的级别,log是具体的日志记录函数。FATAL,ERROR,WARNING,INFORMATION,DEBUG代表日志记录的五个级别,看单词就能明白意思。这里主要讲解一下FileLogger类,这是Tomcat的其中一个日志记录器,它把日志记录在一个文件中,FileLogger的启动方法和关闭仅仅是出发一个生命周期事件,并不做其他的事情:
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; }
这里有一行代码sm.getString("fileLogger.alreadyStarted"),牵涉到国际化的问题,等下再说这个问题。现在先看日志记录器,FileLogger的open方法打开一个文件用来记录日志:
private void open() { // Create the directory if necessary File dir = new File(directory);//directory等于logs,即在文件夹logs下新建日志文件 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; } }
这里得到一个PrintWriter的输出流writer,在log方法记录日志的时候会用到,下面看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); } } }
writer.println把时间和日志信息写进日志文件中。当然,这个日志记录器一般是给Tomcat自己用的,我们也可以实现Logger接口,然后重写它的open方法(打开我们自己的日志文件)和log方法(用来在我们自己的日志文件中记录日志信息)。
现在再来看刚才提到的代码sm.getString("fileLogger.alreadyStarted")。在理解这句代码前先看一个jdk的类ResourceBundle,这个类提供了国际化的方便。这个类的作用就是读取.properties文件,但是会根据文件名来获取当前系统的语言信息,然后读取对应文件的属性值。当然首先要有各国不同的属性文件,才能国际化,Tomcat的每个包下都有几个不同的属性文件,org.apache.catalina.logger包下有如下三个属性文件:
LocalStrings_es.properties LocalStrings_ja.properties LocalStrings.properties
分别表示三种语言的属性文件。LocalStrings.properties属性文件是默认的属性文件。看LocalStrings.properties属性中的内容:
fileLogger.alreadyStarted=File Logger has already been started fileLogger.notStarted=File Logger has not yet been started tomcatLogger.alreadyStarted=Tomcat Logger has already been started tomcatLogger.notStarted=Tomcat Logger has not yet been started
ResourceBundle类通过getBundle方法获取,参数是属性文件的包名家名字前缀,上面就是包名加LocalStrings。通过getString(String key)方法获取属性文件中的参数:
现在来看代码sm.getString("fileLogger.alreadyStarted"),sm是StringManager的实例,在FileLogger中已经初始化:
private StringManager sm =StringManager.getManager(Constants.Package);
Constants.Package得到包的名字,getManager方法代码如下:
public synchronized static StringManager getManager(String packageName) { StringManager mgr = (StringManager)managers.get(packageName); if (mgr == null) { mgr = new StringManager(packageName);//新建一个StringManager managers.put(packageName, mgr); } return mgr; }
代码很好理解,如果已经有StringManager实例了就直接从managers(这是一个Hashtable)中拿,没有就新建一个。看StringManager的构造方法:
private StringManager(String packageName) { String bundleName = packageName + ".LocalStrings"; bundle = ResourceBundle.getBundle(bundleName); }
看到我们熟悉的ResourceBundle类了,根据上面的讲解,ResourceBundle.getBundle(bundleName)能拿到默认的属性文件,也就是上面的LocalStrings.properties文件。再回到sm.getString("fileLogger.alreadyStarted"),看sm的getString方法:
public String getString(String key) { if (key == null) { String msg = "key is null"; throw new NullPointerException(msg); } String str = null; try { str = bundle.getString(key); } catch (MissingResourceException mre) { str = "Cannot find message associated with key '" + key + "'"; } return str; }
重点是budle.getString(key),这句代码能拿到LocalStrings.properties文件的key属性(这里是fileLogger.alreadyStarted)的值,即File Logger has already been started。这样我们便能定义多个属性文件,一个表示英文,一个表示汉语,一个属性文件表示一个语言,就能实现应用的国际化了。
发表评论
-
Tomcat源码分析(一)--服务启动
2012-07-05 11:11 454对Tomcat感兴趣是由 ... -
Tomcat源码分析(二)--连接处理
2012-07-06 08:35 411目标:在这篇文章希望搞明白http请求到tomcat后是 ... -
Tomcat源码分析(三)--连接器是如何与容器关联的?
2012-07-06 11:18 573这篇文章要弄懂一个问题,我们知道,一个链接器是跟一个容器关 ... -
Tomcat源码分析(四)--容器处理链接之责任链模式
2012-07-07 16:21 391目标:在这篇文章希望搞明白connector.getCont ... -
Tomcat源码分析(五)--容器处理连接之servlet的映射
2012-07-08 09:32 432本文所要解决的问题:一个http请求过来,容器是怎么知道选 ... -
Tomcat源码分析(七)--单一启动/关闭机制(生命周期)
2012-07-10 12:23 473在前面的大部分文章都是讲连接器和容器的,以后的内容会偏向写一 ... -
Tomcat源码分析(八)--载入器
2012-07-10 20:14 546在讲Tomcat的载入器之前,先要了解一下java的类加载 ... -
Tomcat源码分析(十)--部署器
2012-07-12 09:02 532我们知道,在Tomcat的世界里,一个Host容器代表一 ... -
Tomcat源码分析(九)--Session管理
2012-07-11 15:16 676在明白Tomcat的Session机 ...
相关推荐
源码分析对于开发者来说是一种深入理解软件内部运作机制的重要途径。`apache-tomcat-8.5.47-src.zip`这个压缩包包含了Tomcat 8.5.47版本的完整源代码,这对于想要研究Tomcat工作原理、优化性能或者进行自定义扩展的...
Apache Tomcat 7.0.81 源码分析 Apache Tomcat 是一个流行的开源软件,用Java语言编写,是实现Java Servlet和JavaServer Pages(JSP)规范的应用服务器,广泛用于Web应用的开发和部署。源码的下载对于开发者来说...
Catalina负责管理Web应用程序,Jasper处理JSP文件的编译和执行,Coyote处理网络通信,而Juli则提供详细的日志记录。 2. **Catalina组件** - **Container**:Tomcat中的每个组件都是一个Container,负责处理请求并...
Apache Tomcat源码分析 Apache Tomcat是一款广泛应用的开源Java Servlet容器,它是Java EE Web应用程序的标准实现。Tomcat源码的深入理解对于Java Web开发者来说是至关重要的,它可以帮助我们了解HTTP服务器的工作...
3. **logs**:记录Tomcat运行时的日志信息,对于调试和问题排查至关重要。 4. **temp**:Tomcat在运行过程中产生的临时文件存储在这里。 5. **webapps**:这是默认的应用部署目录,任何在此目录下的Web应用都会被...
- **日志和调试**:提供了详细的日志记录和调试功能,有助于问题排查。 4. **源码分析** 解压“jakarta-tomcat-connectors-jk2-2.0.4-src”后,我们可以深入研究JK2的源代码结构,包括核心的模块、协议处理器、...
9. **国际化和本地化**:Tomcat如何支持多种语言环境。 通过深入研究这些源代码,开发者可以更好地理解和优化Tomcat服务器,甚至为它贡献代码。同时,这也为开发自己的Java Web应用程序提供了宝贵的经验,帮助理解...
### Tomcat源码研究知识点概览 #### 1.1 Catalina.bat脚本解析 - **脚本功能**:`catalina.bat`是Tomcat启动过程中的关键脚本之一,其主要作用在于构建合适的Java命令行参数,进而启动Tomcat服务。此脚本根据环境...
Apache Tomcat 7.0.29源码分析 Apache Tomcat是一款开源的Java Servlet容器,主要用于实现Java Servlet和JavaServer Pages(JSP)技术。它由Apache软件基金会开发并维护,是Java EE(现在称为Jakarta EE)应用...
Tomcat使用多线程模型处理并发请求,源码中可以看到Executor(执行器)和ThreadPool(线程池)的概念,它们有助于提高系统效率和资源利用率。 6. **安全与权限控制**: Tomcat支持多种安全机制,如SSL/TLS加密、 ...
8. **性能优化**:Tomcat源码分析可以帮助开发者了解如何优化性能,如调整线程池大小,启用NIO(非阻塞I/O)模式,减少内存泄漏等。 9. **扩展性**:Tomcat源码允许开发者自定义Valves(请求处理管道中的组件)、...
4. **logs**:日志文件的默认存储位置,记录Tomcat运行时的信息和错误。 5. **webapps**:默认的Web应用程序部署目录,任何在此目录下的WAR文件或目录都会被Tomcat自动部署为Web应用。 6. **work**:存放Tomcat在...
`bin`存放启动和停止服务器的脚本,`conf`存储配置文件,`lib`包含运行Tomcat所需的JAR文件,`logs`记录日志,`webapps`是部署Web应用的位置,`work`用于存放JSP编译后的类文件。 2. **核心组件**: - `Catalina`...
在"tomcat-connectors-1.2.26-src.tar.gz"这个压缩包中,包含了Tomcat Connectors 1.2.26版本的源代码,这为我们提供了一个深入了解其工作原理和定制化开发的机会。 一、AJP协议 AJP协议是一种轻量级的通信协议,...
Tomcat作为Servlet容器,负责加载、实例化和管理Servlet。 - **JSP**:JavaServer Pages(JSP)是一种用于创建动态网页的技术,将HTML、XML或者其他标记语言与Java代码结合,使得开发者可以将表现层和业务逻辑分离...
- **Access Log Valve**: 访问日志记录,用于监控和分析应用的访问行为。 6. **性能优化** - **Keep-Alive**: 支持持久连接,减少TCP握手和释放的开销。 - **NIO、APR(Apache Portable Runtime)**: 提供高性能...
10. **错误处理与日志记录**:Tomcat使用`logging`框架进行日志记录,通过配置可以调整日志级别,方便调试和问题定位。 通过深入研究"apache-tomcat-7.0.34-src.zip"中的源代码,开发者可以学习到服务器架构设计、...
Tomcat的日志文件位于`logs`目录下,包括`catalina.out`、`host-manager`、`manager`等,它们记录了服务器运行过程中的信息,对于故障排查非常有帮助。 9. **常见问题** 使用过程中可能会遇到如端口冲突、内存...
4. **Juli**:这是Tomcat的日志框架,提供了自定义的日志记录策略,使开发者能够更好地控制日志输出。 5. **Web应用部署**:Tomcat支持通过XML配置文件(context.xml)或在webapps目录下放置WAR文件自动部署Web应用...