Tomcat研究之组件结构

系统 1648 0

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

作者:chen77716 发表于2005-4-12 18:26:00 原文链接
阅读:1011 评论:0 查看评论

Tomcat研究之组件结构


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论