Tomcat研究之组件结构

Tomcat研究之组件结构

 

 

大家好,上篇介绍了《Tomcat研究之ClassLoader》,这篇我们介绍组件结构

     在没有任何实质性资料的前提下研究Tomcat的内核将是非常困难的事情,但无论如何还有opensource,我们至少可以跟踪Tomcat成百上千的类,为了我们能彻底解开Tomcat的面纱,我们还是要继续努力.

   通过UML类图不难看出,Core包里面最重要的一个类是ContainerBase,而这个抽象类实现了Container, Lifecycle, Pipeline, MBeanRegistration, Serializable接口, Serializable接口大家都已很熟悉,我们重在研究前几个接口,因为我们猜想整个Tomcat的部分构架可能是建立在这几个基础接口上.

    在进入分析之前我们先回忆一下config.xml(server.xml)文件,从这个文件及apache的文档我们大体可以了解到Tomcat宏观上是有下面几个部分组成:

-          Server  server元素是JVM的入口点,整个配置文件只有一个,因为server不是容器(container),因此不能嵌套子组件.server在某一指定的端口监听shutdown命令.server可以包含一个或多个service实。

-          Service service有共享同一个Container的一个或多个Connectors组成,一般Service就是一个Engine,但没有明确规范要求如此.因为Service不是一个Container,因此不能在里面嵌套子组件(比如Loggers/Valves)。

-          Connector connector就是一个Tomcat与客户端的连接,Tomcat有两种典型的Connector:http,JK2.http connector监听来自Browser的连接(通常在我们熟悉的8080端口),JK2.来自其他WebServer的请求(默认在8009端口监听)。Connector会把获得的请求交给Engine处理。

-          Engine Engine下可以配置多个虚拟主机Virtual Host,每个虚拟主机都有一个域名当Engine获得一个请求时,它把该请求匹配到某个Host上,然后把该请求交给该Host来处理Engine有一个默认虚拟主机,当请求无法匹配到任何一个Host上的时候,将交给该默认Host来处理

-          Host host代表一个虚拟主机,默认是localhost,host下可以部署多个web application,在我们实际应用中一般要考虑问题的对象就是host

 

 

1.         org.apache.catalina.Lifecycle

通用的组件声明周期接口,一般Tomcat的组件都要实现这个接口(但不是必须的),这个接口是为所有组件提供相同的start和stop。主要方法有:

//增加一个监听器

public void addLifecycleListener(LifecycleListener listener);

 

 

/**

*这个方法应该在任何public方法被调用前被调用

*该方法发送一个START_EVENT事件到所有注册到

*该组件的监听器

*/

public void start() throws LifecycleException;

 

 

/**

*这个方法应该在所有public方法被调用之后被调用

*该方法发送一个STOP_EVENT事件到所有注册到

*该组件的监听器

*/

public void stop() throws LifecycleException;

 

 

2.         org.apache.catalina. LifecycleListener

该接口用于监听一些重要事件(包括实现了Lifecycle接口组件产生的start,stop事件)

主要方法是:

//处理监听到的事件

public void lifecycleEvent(LifecycleEvent event);

 

 

 

 

3.         org.apache.catalina.Container

容器是用于从客户端取得请求(request)并且处理请求并回复给客户端(response)的对象。容器可以支持(可选)pipeline,以便能在运行时按配置的顺序处理请求。

在Tomcat里面,容器在概念上存在以下及层:

Engine    请求处理入口点,可以包含多个Host和Context

Host        代表一个虚拟主机

Context        代表单个ServletContext,可以包含多个Wrappers

Wrapper  代表单个Servlet,如果Servlet实现了SingleThreadModel,可以代表单个Servlet的多个实例。

容器为了实现自己的功能经常要绑定一些其他组件,这些组件的功能可能被共享,也可以被单独定制,下面是被使用的组件:

Loader       ClassLoader,装载Java Classes

Logger       实现了ServletContext的log方法,用于记录日志

Manager         管理与容器绑定的session池

Realm        用户安全管理

Resources  JNDI资源访问

主要的方法:

 

 

//增加容器监听器

public void addContainerListener(ContainerListener listener);

 

 

//增加property监听器

public void addPropertyChangeListener(PropertyChangeListener listener);

 

 

/**

*处理Request,并产生相应地Response

*param request 处理的请求

*param  response 产生的response

*/

public void invoke(Request request, Response response)   throws IOException, ServletException;

 

 

4.         org.apache.catalina. ContainerListener

容器事件监听器,注意的是start,stop是正常的生命周期事件(LiftcycleEvent)不是容器事件。主要方法:

 

 

//处理容器事件

public void containerEvent(ContainerEvent event);

5.         org.apache.catalina. Pipeline

Pipleline是Valve的集合,当invoke方法被调用时,它会按指定的顺序调用Valve,它总是要求有一个Valve必须处理传递的request(一般是最后一个)并产生response,否则就把request传递到下一个Valve。

  一般一个容器仅绑定一个Pipleline实例,一般说来容器会把处理request的功能封装到一个容器绑定的Valve里(这个Valve应该在Pipleline最后被执行)。为了完成这个功能,Pipleline提供了setBasic()方法以保证Valve被最后执行,而其他Valve按顺序被调用。

6.         org.apache.catalina.Valve

     Valve是被绑定在一个Container上的请求处理组件,一组Valve被按顺序绑定在一个Pipleline上。Valve最重要的一个方法是:

 

 

/**

 *一个Valve可能按照一定的顺序执行下面的动作

 *1.检查并且(或者)修改指定的Request和Response属性

 *2.检查Request属性,生成相应的Response并返回控制权到调用者

 *3.检查Request和Reponse属性,包装这些对象并增强它们的功能,然后把它们传

到下一个组件

     *4.如果相应的Response没有被产生(并且控制权也没有被返回)调用Pipleline

上的下一个Valve(如果有)通过方法context.invokeNext()

     *5.检查(但不修改)Response属性(调用后面的Valve或Container产生的)

     *Valve一定不能作下面的事情

     *1.改变Request的一些属性(Change request properties that have

        already been used to direct the flow of processing control

        for this request)

       *2.创建一个已经被创建并且已经被传递的Response

     *3.在调用invokeNext()方法并返回后修改包含Response的HTTP Header信息

     *4.在invokeNext()调用返回后在绑定Response上的输出流上作任何调用

     *@param request 将被处理的Request

     *@param response 将被创建的Response

     *@param context 被用来调用下一个Valve的Valve Context

      public void invoke(Request request, Response response,

                       ValveContext context)

        throws IOException, ServletException;

7.         org.apache.catalina.ValveContext

一个ValveContext是这样一种机制:一个Valve可以触发下一个Valve的调用,而不必知道机制的内在实现。

8.         org.apache.catalina.Engine

Engine是一个容器,是Cataline的Servlet的入口点。

当发布一个连接到Web Server的Cataline时可能不使用Engine,因为Connectior将使用Web Server的资源决定使用哪个Context处理Request。

附属于Engine的子容器根据Engine实现的不同可能是Host或Context(单个Servlet Context)。

如果使用了Engine,在Cataline的层次中它就是顶层容器,因此setParent()应改抛出IllegalArgumentException异常。从Engine下面几个方法我们可以看出其的结构:

 

 

/**

    * 设定Engine附属的Service

    * @param service The service that owns this Engine

    */

    public void setService(Service service);

 

 

    /**

     * Set the default hostname for this Engine.

     *

     * @param defaultHost The new default host

     */

    public void setDefaultHost(String defaultHost);

 

 

    /**

     * Set the DefaultContext

     * for new web applications.

     *

     * @param defaultContext The new DefaultContext

     */

    public void addDefaultContext(DefaultContext defaultContext);

 

 

9.         org.apache.catalina. Host

Host是一个容器,它代表一个虚拟主机。

当发布一个连接到Web Server的Cataline时可能不使用Host,因为Connectior将使用Web Server的资源决定使用哪个Context处理Request。

Host所附属的父容器通常是Engine,附属于Host的子容器通常是Context(单个Servlet Context)。

Host接口里面的方法多数都是关于修改Host属性及设定默认的Context。这里我们不再一一列举。

10.      org.apache.catalin. Context

      Context是一个容器,它代表一个ServletContext,一个Cataline Engline中的单个的Web Application。Context所附属的父容器是Host,附属于Context的子容器是Wrapper(代表单个Servlet)。Context接口里面多数是关于Web Application的设置的方法,我们可以参考Web.xml文件研究里面的方法,里面多数方法都是如何读取Web.xml文件里的资源。

11.      org.apache.catalina.Wrapper

Wrapper是一个容器,它代表单个Servlet。Wrapper管理Servlet的生命周期,包括调用init()和destory()方法。

Wrapper所附属的父容器是Context,没有附属于Wrapper的子容器,方法addChild()应该抛出IllegalArgumentException异常。

Wrapper接口里面的方法都是关于读取Servlet的属性,可以参考Web.xml文件里面关于<servlet>标签的定义。

12.  org.apache.catalina.Server

Server是整个Catalina容器的入口点,可以包含多个Service和顶层资源元素。一般说来实现Server接口的类也应该同时实现Lifecycle接口,当start()和stop()方法被调用的时候调用Service相应的方法。

   Server负责在指定的端口监听连接,当有连接被接受的时候,Server会分析请求的第一行信息,如果是SHUTDOWN则stop服务。可以参考Server.xml文件关于Server的定义。

13.      org.apache.catalina. Service

       Service是一个或多个共享同以Container的Connectiors的集合。

   JVM可以包含一个或多个Service实例,但它们相互之间是完全独立的,它们仅共享JVM的资源。

14.  org.apache.catalina. Connector

      Connector是一个从客户端接受请求(request)并生成回应(reponse)的组件。一个Connection通常执行下面的逻辑:

1)      从客户端程序接受请求

2)      创建Request和Response,并把下面这些属性设置到这些对象

(1)对所有的Request,connector,protocol,protocol,response,scheme,secure,serverName,serverPort,serverPort属性必须被设置。contentLength,contentType通常也被设置。

3)      对所有的HttpRequests,method,queryString,requestedSessionCookie,requestedSessionId,requestedSessionURL,requestURI,secure属性必须被设置。另外所有addXxx方法也必须被调用以记录cookies,headers和locales信息。

4)      对所有的Responses属性connector,request,stream属性必须被设置。

对HttpResponses来说,connector不会为它设置额外headers信息。

1.         Tomcat整体架构类图

 

 

下篇将从Tomcat的各个组件入手介绍Tomcat。

时间: 2024-08-04 02:53:36

Tomcat研究之组件结构的相关文章

jQuery EasyUI框架中的Datagrid数据表格组件结构详解_jquery

基础DOM结构什么叫"完整的基础DOM结构",这里"基础"的意思是指这个结构不依赖具体数据,不依赖Datagrid的view属性,只要存在Datagrid实例就会存在这样的基础DOM结构:而"完整"的意思是指在冻结列,冻结行,标题,footer,分页这些功能块都存在时候的DOM结构. 要搞清楚Datagrid的工作原理,这个DOM结构必须要烂熟于胸的,我们直接来看这个"基础完整DOM结构"是什么样子的: <!-- dat

Androi“.NET研究”d 源代码结构

简介 在使用Andriod SDK进行应用程序开发的时候,我们需要对源代码进行调试,有可能需要进入到某个Android API函数内部进行跟踪调试.但是,如果目标版本的SDK没有关联对应版本的源代码的话,就会提示你找不到源代码. 图:找不到Android源码的提示 我们都知道Android系统是一个开源工程,在网上可以下载到源代码.一般在网上搜索一下,就会找到各种下载源代码的方法,比如使用Git和Repo,android源代码下载的网址是http://android.git.kernel.org

SWT:实现自我绘制的Button组件

在所有SWT组件中,Button几乎是最常用的,其功能在对于一般的情况来说也足够丰富了.你可以为Button组件设置要显示在其中的文本或者图像.设定ToolTip,甚至只要修改一个风格样式就能得到一个看上去相当不错的方向箭头按钮. 然而,我对Button组件还是不能感到满意.最大的遗憾就是:对它的外观,所能做的工作也就仅限于此了.如果你想让按钮拥有一个漂亮的.渐变色的背景和一些特殊的文字效果,怎么办呢?答案是没有办法.Button类里面似乎没有任何方法提供我想要的功能. 我曾尝试过的第一个想法是

[置顶]【原创】.NET开源压缩组件介绍与入门

       本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 1.前言 作为吉日嘎拉权限管理系统最早的一批学习版用户,学了不少东西,在群里面也结识了很多朋友,更重要的是闲余时间,大家都发布很多可靠的外包工作.这次也是由于吉日嘎拉发布了一个有关"压缩文件损坏检测"的外包任务,最早在2009年用C#很简单的使用过压缩组件,这次有了这个需求,才所以才深入研究一番,顺便有了这篇博客. 在日常项目开

.NET开源压缩组件介绍与入门

原文 http://www.cnblogs.com/asxinyu/archive/2013/03/05/2943696.html 1.前言 作为吉日嘎拉权限管理系统最早的一批学习版用户,学了不少东西,在群里面也结识了很多朋友,更重要的是闲余时间,大家都发布很多可靠的外包工作.这次也是由于吉日嘎拉发布了一个有关"压缩文件损坏检测"的外包任务,最早在2009年用C#很简单的使用过压缩组件,这次有了这个需求,才所以才深入研究一番,顺便有了这篇博客. 在日常项目开发过程中,操作Zip或者RA

jetty的工作原理以及与tomcat 的比较

Jetty 的基本架构 Jetty 目前的是一个比较被看好的 Servlet 引擎,它的架构比较简单,也是一个可扩展性和非常灵活的应用服务器,它有一个基本数据模型,这个数据模型就是 Handler,所有可以被扩展的组件都可以作为一个 Handler,添加到 Server 中,Jetty 就是帮你管理这些 Handler. Jetty 的基本架构 下图是 Jetty 的基本架构图,整个 Jetty 的核心组件由 Server 和 Connector 两个组件构成,整个 Server 组件是基于 H

Tomcat 系统架构与设计模式--工作原理

本文以 Tomcat 5 为基础,也兼顾最新的 Tomcat 6 和 Tomcat 4.Tomcat 的基本设计思路和架构是具有一定连续性的. Tomcat 总体结构 Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的"七寸".下面是 Tomcat 的总体结构图: 图 1.Tomcat 的总体结构 从上图中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在

深入理解Tomcat系列之一:系统架构

前言 Tomcat是Apache基金组织下的开源项目,性质是一个Web服务器.下面这种情况很普遍:在eclipse床架一个web项目并部署到Tomcat中,启动tomcat,在浏览器中输入一个类似http://localhost:8080/webproject/anyname.jsp的url,然后就可以看到我们写好的jsp页面的内容了.一切都是那么自然和顺理成章,然而这一切都是源于tomcat带给我们的,那么在tomcat背后,这一切又是怎么样发生的呢?带着对tomcat工作原理的好奇心,我决定

深入理解Tomcat系列之一:系统架构(转)

前言 Tomcat是Apache基金组织下的开源项目,性质是一个Web服务器.下面这种情况很普遍:在eclipse床架一个web项目并部署到Tomcat中,启动tomcat,在浏览器中输入一个类似http://localhost:8080/webproject/anyname.jsp的url,然后就可以看到我们写好的jsp页面的内容了.一切都是那么自然和顺理成章,然而这一切都是源于tomcat带给我们的,那么在tomcat背后,这一切又是怎么样发生的呢?带着对tomcat工作原理的好奇心,我决定