最近在学习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如何用管道阀来简化开发流程和增强程序扩展性。

最新文章

  1. Dubbo 备注
  2. Myeclipse2016部署tomcat服务(别的服务类似)配置环境
  3. linux 文件系统解析及相关命令
  4. VS2010设置C++包含目录和库目录
  5. Restrict each user to a single session in window server 2008 R2 or 2012
  6. 算法导论_ch2
  7. Qt之模型/视图(委托)
  8. VLC笔记 它 立志
  9. hadoop 完全分布式
  10. javascript生成新标签的三种方法
  11. JS复习:二十一章
  12. Linux+Apache2.4+PHP5.6+MySQL5.6源码安装步骤
  13. 根据矩阵变化实现基于 HTML5 的 WebGL 3D 自动布局
  14. Windows平台下的内存泄漏检测
  15. PE知识复习之PE的节表
  16. Go中局部全局变量的区分
  17. Redis配置主从复制
  18. c# 有序链表合并 链表反转
  19. 【洛谷P3960】列队题解
  20. Day26--Python--包

热门文章

  1. Python简单线程间通信
  2. DCMTK读取DICOM文件头信息的三种方法
  3. Windosw系统——常见的问题
  4. ssm整合-错误3
  5. mysql悲观锁与乐观锁
  6. python -- sftp的方式下载终端文件
  7. POJ 1981 最大点覆盖问题(极角排序)
  8. C# 在窗口绘制图形(打点、画圆、画线)
  9. C# 设定弹出窗体位置
  10. 陌生又熟悉的数据库之ID增加