tomcat(7)日志记录器

【0】README
0.1)本文部分文字描述转自:“深入剖析tomcat”,旨在学习 “tomcat的日志记录器” 的基础知识;
0.2)intro to 日志记录器:日志记录器是用来记录消息的组件;
0.3)for complete source code, please visit https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter7
0.4)温馨建议:建议阅读本文之前,已阅读过 tomcat(1~6)的系列文章,因为它们是环环相扣的;

【1】Logger接口(日志记录器都必须实现 org.apache.catalina.Logger接口)
1)Logger接口提供了一些log() 方法来写日志;
2)Logger的某些log() 方法接受一个日志级别,定义了5种日志级别:FATAL, ERROR, WARNING, INFORMATION , DEBUG;
3)获取和设置日志级别:getVerbosity() and setVerbosity();
4)将日志记录器和某servlet容器关联: getContainer() and setContainer();
5)添加或移除PropertyChangeListener:addPropertyChangeListener() and removePropertyChangeListener();

【2】Tomcat的日志记录器
1)Tomcat提供了3种日志记录器,分别是:FileLogger, SystemErrorLogger, SystemOutLogger;类图如下:(干货——Tomcat提供了3种日志记录器

【2.1】LoggerBase类(以tomcat4的 LoggerBase为例)
1)LoggerBase类:实现了Logger接口中的除log(String name)外的所有方法;
2)LoggerBase类的日志等级设置:日志等级使用一个名为 verbosity来设置,默认值为 ERROR;
protected int verbosity = ERROR; // LoggerBase.java
3)接收日志等级的两个log重载方法:只有当传入的日志等级比当前实例中verbosity变量指定的等级低时,才会调用重载方法log(String msg)来记录日志;
public void log(String message, int verbosity) {  // LoggerBase.javaif (this.verbosity >= verbosity)log(message);}public void log(String message, Throwable throwable, int verbosity) {  // LoggerBase.javaif (this.verbosity >= verbosity)log(message, throwable);}
【2.2】SystemOutLogger类
1)该类的特点:接收到的每条日志消息都会传递给 System.out.println();
【2.3】SystemErrLogger类
1)该类的特点:接收到的每条日志消息都会传递给 System.err.println();

【2.4】FileLogger类
1)intro: 它将servlet容器中接收到的日志消息写到一个文件,并且可以选择是否要为每条消息添加时间戳;
2)LoggerBase.start() 方法 和 LoggerBase.stop()方法:Tomcat4中,LoggerBase() 类的start方法和stop方法只负责启动和关闭文件日志记录器时触发触发生命周期事件,并不做其他事情,源代码如下:
3)FileLogger.log()方法(最重要的方法):该方法会将接收到的日志消息写到一个日志文件中,(当日期发生变化时,log方法会关闭当前日志文件,并打开一个新文件),下面看一下open方法,close方法和log方法的具体实现:
3.1)open()方法:
step1)检查要创建的日志文件所在的目录是否存在,不存在,就创建该目录。目录位置是存储在类变量 directory中的;
step2)根据目录路径,创建位于指定位置的日志文件,并添加相应的前缀,当前日志和后缀;
step3)创建 java.io.PrintWriter实例,具体执行写路径名操作的是 java.io.FileWriter对象的实例;
step4)将PrintWriter实例赋值给 writer变量;
private void open() { // FileLogger.open() 方法// Create the directory if necessaryFile dir = new File(directory);if (!dir.isAbsolute()) // step1dir = new File(System.getProperty("catalina.base"), directory);dir.mkdirs();// Open the current log filetry {String pathname = dir.getAbsolutePath() + File.separator +prefix + date + suffix; // step2writer = new PrintWriter(new FileWriter(pathname, true), true); //step3,4} catch (IOException e) {writer = null;}}
3.2)close()方法:
step1)intro:close方法负责确保将 PrintWriter 实例中所有的日志消息都写到文件中,关闭 PrintWriter 实例,将其引用设置为null,并将日期字符串清空;
private void close() { // FileLogger.close() 方法if (writer == null)return;writer.flush();writer.close();writer = null;date = "";}
3.3)log()方法:
step1)该方法会先创建 java.sql.Timestamp类 的一个实例;(使用 Timestamp类的toString() 方法可以获取当前日期的字符串表示形式,toString() 方法返回的日期格式为 yyyy-mm-dd hh:mm: ss.fffffffff, fffffffff 表示从00:00:00 起经过的纳秒数,若是只想要获取日期和小时,可以调用 subString方法,String substr = ts.toString().substring(0,19))
step2)获取日期部分;
String tsDate = tsString.substring(0,10);
step3)log方法将tsDate与 字符串形式的变量date 相比较。若不等,则log方法会关闭当前日志文件,并打开一个新日志文件;
step4)log方法将日志信息写到 PrintWriter实例中,而PrintWriter实例将输出流写入到日志文件中。(是否加上时间戳,依据布尔变量 timestamp)
public void log(String msg) { FileLogger.log() 方法// Construct the timestamp we will use, if requestedTimestamp ts = new Timestamp(System.currentTimeMillis()); // step1String tsString = ts.toString().substring(0, 19); // step1String tsDate = tsString.substring(0, 10); // step2// If the date has changed, switch log filesif (!date.equals(tsDate)) { // step3synchronized (this) {if (!date.equals(tsDate)) {close();date = tsDate;open(); // this highlight line.}}}// Log this message, timestamped if necessaryif (writer != null) { // step4if (timestamp) {writer.println(tsString + " " + msg);} else {writer.println(msg);}}}

【3】应用程序
1)本文的应用程序同章节6的应用程序相似,区别在于, SimpleContext 对象关联了一个 FileLogger 组件。
public final class Bootstrap {public static void main(String[] args) {Connector connector = new HttpConnector();Wrapper wrapper1 = new SimpleWrapper(); // 创建Wrapper容器wrapper1.setName("Primitive"); // 填充容器wrapper1.setServletClass("servlet.PrimitiveServlet");Wrapper wrapper2 = new SimpleWrapper();wrapper2.setName("Modern");wrapper2.setServletClass("servlet.ModernServlet");Loader loader = new SimpleLoader(); // 创建类加载器Context context = new SimpleContext(); // 创建Context容器,可以包含多个Wrapper容器context.addChild(wrapper1);context.addChild(wrapper2);Mapper mapper = new SimpleContextMapper(); // 创建映射器,提供请求资源的 URI到 请求资源(servlet)名称的映射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 -------- highlightSystem.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);//--------------------------- highlight over.connector.setContainer(context);try {connector.initialize(); // 获得服务器套接字((Lifecycle) connector).start(); // 接收client发出的 http请求,并做处理。((Lifecycle) context).start(); // 触发生命周期事件// make the application wait until we press a key.System.in.read();((Lifecycle) context).stop();}catch (Exception e) {e.printStackTrace();}  }}

Attention)照惯例,本文总结了上述测试用例的调用过程示例图
A1)写在前面:在SimpleContext的start() 方法中调用了 log方法;
A2)log方法的调用steps 如下图所示:


2)运行参数
E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomcat.chapter7.startup.B
ootstrap
SimpleContextLifecycleListener's event before_start
Starting SimpleLoader
Starting Wrapper Primitive
Starting Wrapper Modern
SimpleContextLifecycleListener's event start
Starting context.
SimpleContextLifecycleListener's event after_start
ModernServlet -- init

3)运行结果
3.1)生成的日志文件为(日志路径在 SystemgetProperty("user.dir") + “/webroot”):
2016-04-17 17:16:58 HttpConnector Opening server socket on all host IP addresses
2016-04-17 17:16:58 HttpConnector[8080] Starting background thread
2016-04-17 17:16:58 HttpProcessor[8080][0] Starting background thread
2016-04-17 17:16:58 HttpProcessor[8080][1] Starting background thread
2016-04-17 17:16:58 HttpProcessor[8080][2] Starting background thread
2016-04-17 17:16:58 HttpProcessor[8080][3] Starting background thread
2016-04-17 17:16:58 HttpProcessor[8080][4] Starting background thread
2016-04-17 17:16:58 starting Context
2016-04-17 17:16:58 Context started
3.2)访问记录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331227.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

漫画算法:最小栈的实现

转载自 玻璃猫 程序员小灰 小灰回忆起当时的情景…… 题目:实现一个栈,带有出栈(pop),入栈(push),取最小元素(getMin)三个方法。要保证这三个方法的时间复杂度…

oidc auth2.0_将Auth0 OIDC(OAUTH 2)与授权(组和角色)集成

oidc auth2.0如果您正在使用Auth0对多个现有应用程序中的用户进行身份验证和授权,则可能需要将下一个Web应用程序与Auth0集成。 有多种方法可以执行此操作,例如,如果要将Jenkins与Auth0集成,则可以使用SAML v2;否则&a…

follow 开源项目关于NoClassDefFoundError错误的解决方法

【0】README0.1)本文旨在po出当我们follow open projects 的时候,遇到一些在open API中不存在(NoClassDefFoundError)的类时的解决方法;【1】problemsolution:1.1)problem:一般case下…

camel apache_如何使用Apache Camel,Quarkus和GraalVM快速运行100个骆驼

camel apache今天,我继续在youtube上练习,并录制了10分钟的视频,介绍了如何创建一个新的Camel and Quarkus项目,该项目包括Rest和HTTP服务以及开箱即用的健康检查和指标。 然后比较在JVM模式下运行示例与使用GraalVM编译的本机的…

漫画算法:找出缺失的整数

转载自 玻璃猫 程序员小灰 小灰一边回忆一边讲述起当时面试的情景...... 题目:一个无序数组里有99个不重复正整数,范围从1到100,唯独缺少一个整数。如何找出这个缺失的整数? 解法一: 创建一个HashMap,以1到…

tomcat(8)载入器

【0】README0.0)本文部分描述转自“深入剖析tomcat”,旨在学习 tomcat(8)载入器 的基础知识;0.1)一个标准web 应用程序中的载入器:简单来说就是 tomcat中的载入器;0.2)servlet容器需要实现一个自…

micrometer_具有InlfuxDB的Spring Boot和Micrometer第3部分:Servlet和JDBC

micrometer在上一个博客中,我们使用由InfluxDB支持的Micrometer设置了React式应用程序。 在本教程中,我们将使用传统的带有JDBC的基于Servlet的阻塞Spring堆栈。 我选择的数据库是postgresql。 我将使用与先前博客文章相同的脚本。 因此,我…

漫画算法:辗转相除法是什么鬼

转载自 玻璃猫 程序员小灰 大四毕业前夕,计算机学院的小灰又一次顶着炎炎烈日, 去某IT公司面试研发工程师岗位…… 半小时后,公司会议室,面试开始…… 小灰奋笔疾书,五分钟后…… 小灰的思路十分简单。他使用暴力…

tomcat(9)Session管理

【0】README0.0)本文部分描述转自“深入剖析tomcat”,旨在学习“tomcat-Session管理” 的基础知识;0.1)Catalina通过一个称为Session 管理器的组件来管理建立的Session对象,该组件由org.apache.catalina.Manager接口来…

micrometer_具有InlfuxDB的Spring Boot和Micrometer第2部分:添加InfluxDB

micrometer自从我们添加了基本应用程序以来,是时候启动InfluxDB实例了。 我们将按照之前的教程进行操作,并添加一个docker实例。 docker run –rm -p 8086:8086 –name influxdb-本地influxdb 是时候在我们的pom上添加微米InfluxDB依赖项了…

漫画:什么是volatile关键字?(整合版)

转载自 永远爱大家的 程序员小灰 ————— 第二天 ————— ———————————— Java内存模型简称JMM(Java Memory Model),是Java虚拟机所定义的一种抽象规范,用来屏蔽不同硬件和操作系统的内存访问差异,让j…

tomcat(supplement)HttpConnector.initialize() 和 start() 方法 以及 StandardContext.start()方法的分析

【0】README 0.0)本文中源代码的背景,参见 tomcat(9)session管理 0.1)本文主要以图片的形式分析他们大致的调用过程; 0.2)HttpConnector org.apache.catalina.connector.http.HttpConnector; 而StandardContext o…

restful rest_HATEOAS的RESTful服务。 超媒体:REST的秘密要素

restful rest在这篇文章中,我们将介绍有关HATEOAS的RESTful服务的综合文章。 超媒体是REST的秘密成分。 1.简介 在本教程的前一部分中,我们花了一些时间来刷新有关REST体系结构样式的基本原理的知识。 业界对REST状态的批判性眼光揭示了一个令人失望的…

漫画:什么是单例设计模式

转载自 永远爱大家的 程序员小灰 ————— 第二天 ————— 单例模式第一版: 1234567891011public class Singleton {private Singleton() {} //私有构造函数private static Singleton instance null; //单例对象//静态工厂方法public static Singleton ge…

如何在工作繁重、睡眠较少的情况下保持旺盛精力?

作者:陈炬 链接:https://www.zhihu.com/question/23177623/answer/47785761 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 本人也在创业,结合《精力管理》一书,说说我…

mockito接口没法赋值_Mockito:无法实例化@InjectMocks字段:类型是接口

mockito接口没法赋值使用Mockito进行Java类的模拟和存根的任何人,可能都熟悉InjectMocks -annotation。 在要测试的类上使用此批注,Mockito将尝试通过构造函数注入,setter注入或属性注入来注入模拟。 魔术成功了,它无声地失败了&a…

tomcat(10)安全性

【0】README0.0)本文部分描述转自“深入剖析tomcat”,旨在学习 tomcat(10)安全性 的基本知识;0.1)servlet技术支持通过配置部署描述器(web.xml)文件来对这些内容进行访问控制;(干货—…

SonarQube 8.3.x中的Maven项目的测试覆盖率报告

几年前,我写了一篇博客文章,介绍如何在SonarQube中生成测试报告,该报告独立于单元测试和集成测试的测试报告中。 从SonarQube 6.2开始,测试报告不再在这些类别中分开(请参阅SonarQube的博客文章 )。 SonarQ…

单例模式懒汉、饿汉和登记

转载自 JAVA设计模式之单例模式本文继续介绍23种设计模式系列之单例模式。 概念:  java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点…

量角器中Selenium定位器的完整指南(示例)

在测试网站的功能时,特别是Web元素(例如单选按钮,文本框,下拉列表等),您需要确保能够访问这些元素。 Selenium定位器正是出于这个目的,通过使用此命令,我们可以识别这些Web元素DOM&a…