最近在学习tomcat源码,算是把tomcat的整个流程梳理通了。

从上图来看,tomcat把模块化使用到了极致,配合组件生命周期的管理,让代码看起来结构清晰,而且很容易进行业务扩展。

1.上图的接口Sever,Service,Connector,Container…..都是一个组件接口,这些组件的关系是,Server包含一个或多个Service,一个Service包含多个Container和与这个Container相关联的Connector,然后Container根据自身需要关联下面的Jasper,Naming…..等组件。Tomcat提供一键式启动和关闭服务,就是以刚刚所说的组件之间的关系来执行的,在启动一个组件的时候,会启动与其相关联的组件,这样会启动所有的组件,而客户端不需要关心其余组件的启动细节。

拿StandardServer的启动来举例:

protected void startInternal() throws LifecycleException {
    fireLifecycleEvent(CONFIGURE_START_EVENT,
null);

//这个方法负责启动前的准备工作,用观察者模式实现
    setState(LifecycleState.STARTING);
//标记组件的状态
    globalNamingResources.start();
//相关联组件的启动

    synchronized (servicesLock) {
        for (int i = 0; i < services.length;
i++) {
            services[i].start();
        }
    }
}

说明一下,组件的启动和关闭时,调用组件的start和stop方法,这两个是模板方法,模板方法中调用的startInternal方法由子类来实现。可以看到Sever会启动globalNamingResource组件和关联的Service组件,实现一键式功能。

2. startInternal方法的第一行

fireLifecycleEvent(CONFIGURE_START_EVENT,
null);

是为了做一些Sever启动前的准备工作,使用的是观察者模式来实现的。

Tomcat的观察者模式主要接口有:Lifecycle,LifecycleEvent,LifecycleListener,LifecycleSupport。

其中LifecycleListener是观察者,负责等待通知然后进行一些与发送的事件想匹配的操作,具体实现类有ContextConfig, HostConfig, EngineConfig,LifecycleEvent
是发送的事件,Lifecycle是被观察者(主题),具体的实现类有StandardServer,StandardContext等等组件,组件启动的时候,会将启动的动作封装成一个事件,然后调用观察者的回调方法,来进行相关操作,LifecycleSupport是一个生命周期的管理类,组件的观察者的管理委托LifecycleSupport来实现,因此所有的组件中都有一个LifecycleSupport的引用,在容器类的抽象类ContainerBase中代码如下:

protected LifecycleSupport lifecycle = new
LifecycleSupport(this);

public void addLifecycleListener(LifecycleListener listener) {

lifecycle.addLifecycleListener(listener);

}

public LifecycleListener[] findLifecycleListeners() {

return lifecycle.findLifecycleListeners();

public void removeLifecycleListener(LifecycleListener listener) {

lifecycle.removeLifecycleListener(listener);

}

对观察者的管理以及动作的触发,都委托LifecycleSupport来实现。

这里主要做三件事:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。每一层次的容器都这样启动,最终整个Tomcat启动完毕。

3. Tomcat中有四种不同的容器:

Engine:代表整个Catalina servle引擎

Host:代表虚拟主机

Context:代表某个web应用

Wrapper:代表某个应用中的servlet

这些容器都是父子的关系,Engine位于最顶层,一个Engine包含多个Host,一个Host(虚拟主机)包含多个Context(web应用),一个Context(web 应用)包含多个Wrapper(servlet),Wrapper位于最底层,没有孩子。当父容器启动时,相应的子容器也应该启动,子容器的子容器也启动。

4.好了,先说到这儿,还有一部分容器管道没有说,下次再介绍一下tomcat如何用管道阀来简化开发流程和增强程序扩展性。

Tomcat源码浅析的更多相关文章

  1. HashMap的源码浅析

    一.HashMap 的数据结构 Java7 及之前主要是"数组+链表",到了 Java8 之后,就变成了"数组+链表+红黑树". 二.Java7 源码浅析: 在 ...

  2. 【深入浅出jQuery】源码浅析--整体架构

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  3. 【深入浅出jQuery】源码浅析2--奇技淫巧

    最近一直在研读 jQuery 源码,初看源码一头雾水毫无头绪,真正静下心来细看写的真是精妙,让你感叹代码之美. 其结构明晰,高内聚.低耦合,兼具优秀的性能与便利的扩展性,在浏览器的兼容性(功能缺陷.渐 ...

  4. svn工具安装下载Tomcat源码以及导入eclipse

    安装 1.svn下载地址 https://tortoisesvn.net/downloads.html 2.语言包下载 3.先安装svn,在直接安装语言包 4.桌面右键可以看到相关svn信息 下载To ...

  5. Tomcat源码导入eclipse的步骤

    Tomcat源码导入eclipse 一.下载源码 1.  进入Apache 官网:http://tomcat.apache.org/ 2.  在左边侧选择要下载的源码的版本. 3.  或者直接通过Ar ...

  6. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

  7. 75篇关于Tomcat源码和机制的文章

    75篇关于Tomcat源码和机制的文章 标签: tomcat源码机制 2016-12-30 16:00 10083人阅读 评论(1) 收藏 举报  分类: tomcat内核(82)  版权声明:本文为 ...

  8. Eclipse导入Tomcat源码(转)

    想要研究下Tomcat的体系结构或者源码,最好将Tomcat的源码导入到ide中,编写实例进行代码跟踪(debug). 这里参考了网上一些资料,将自己操作过程记个流水账. 准备: 1.Tomcat源码 ...

  9. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

随机推荐

  1. 爬虫学习(十三)——xpath基础学习

    lxml的作用 lxml是HTML.xml的解析器,主要的功能是如何解析和提取HTML和xml数据 lxml和正则一样,也是使用C来实现的,是一款高性能的python HTML/xml解析器,我们可以 ...

  2. Maven - 依赖冲突

    依赖冲突有两个规则: 短路优先范例:A -> B -> C -> X-2.0.0A -> D -> X-1.0.0那么A -> X-1.0.0这个版本 先声明优先范 ...

  3. Hutool Wiki For java

    发现一款不错的java工具类, http://www.hutool.cn/ Hutool的使用文档. 项目见 https://github.com/looly/hutool 以及 http://git ...

  4. Jenkins搭建CI/CD

    所需Jenkins插件: Maven Integration pluginPublish Over SSHSSH plugin 1.配置全局工具 配置JDK: 配置Git: 配置maven: 2.创建 ...

  5. VM虚拟机里的Ubuntu系统怎么设置屏幕分辨率

    说白了就是安装VMWare tools工具,步骤如下: 1)在VMWare中启动ubuntu虚拟机 2)在VMWare中:右键单击启动虚拟机,点击[安装vmware tools] 3)在ubuntu中 ...

  6. GIL 线程池 进程池 同步 异步

    1.GIL(理论 重点)2.线程池 进程池3.同步 异步 GIL 是一个全局解释器锁,是一个互斥锁 为了防止竞争解释器资源而产生的 为何需要gil:因为一个python.exe进程中只有一份解释器,如 ...

  7. 进程、线程、协程和GIL(二)

    上一篇博客讲了进程.线程.协程和GIL的基本概念,这篇我们来说说在以下三点: 1> python中使用threading库来创建线程的两种方式 2> 使用Event对消来判断线程是否已启动 ...

  8. idea debug启动项目慢或者启动不了

    使用debug无法启动项目但是使用run就可以启动程序,而且启动比以前的debug模式快的多 原因: 启动不了的原因是在项目中的方法上打了断点,导致项目无法继续编译 取消方法断点就可以了 在idea官 ...

  9. dfs序线段树

    dfs序+线段树,啥?如果在一棵树上,需要你修改一些节点和查询一些节点,如果直接dfs搜的话肯定超时,那用线段树?树结构不是区间啊,怎么用?用dfs序将树结构转化为一个区间,就能用线段树进行维护了. ...

  10. STM8 输出比较极性

    PWM输出的信号极性有两个选项决定,一个选项是PWM模式,另一个选项是输出极性控制位. 请看定时器的框图,PWM模式的选择决定OC1REF的极性, 例如当选择PWM1模式时,OC1REF信号是&quo ...