Tomcat总体结构

Tomcat总体结构用下图来表示

图片摘自:https://blog.csdn.net/jiaomingliang/article/details/47393141

从上图可以看到,Tomcat是由Server、Service、Engine、Connerctor、Host、Context组件组成。使用过Tomcat的人对这些组件名是不是有种似曾相识的感觉。回忆一幕幕,好像还是想不起来,哈哈! 好吧,别回忆了,我来告诉你。在Tomcat的conf目录中有一个server.xml文件,打开一看,眼前豁然开朗了,是不是发现server.xml文件中已经包含了上述所有组件。保留server.xml文件中本文将要介绍的核心组件,组件配置及简要介绍如下:

<?xml version="1.0" encoding="UTF-8"?><!--
Server标签对应org.apache.catalina.Server接口。
Server元素表示整个Catalina servlet容器。
它的属性代表整个servlet容器的特征。
Server可以包含一个或多个Services,以及顶级命名资源集。
-->
<Server port="8005" shutdown="SHUTDOWN"><!--Service标签对应org.apache.catalina.Service接口。Service包含一个或多个Connectors,它们共享一个Container来处理所有请求。--><Service name="Catalina"><!--Connector代表一个用来接收请求并返回的端--><Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443"/><!--Tomcat的Engine实现独立分析请求中包含的HTTP头,并传递它们到适当的主机(虚拟主机)。--><Engine name="Catalina" defaultHost="localhost"><Host name="localhost" appBase="webapps"unpackWARs="true" autoDeploy="true"><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="localhost_access_log" suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b"/></Host></Engine></Service>
</Server>

Server

Server对应Tomcat源码中的org.apache.catalina.Server接口,其实现类为:org.apache.catalina.core.StandardServer,继承关系图如下图所示:

  • Server继承至LifeCycle,LifeCycle是一个非常重要的接口,各大组件都继承了这个接口,用于管理tomcat的生命周期,比如init、start、stop、destory;另外,它使用了观察者模式,LifeCycle是一个监听者,它会向注册的LifecycleListener观察者发出各种事件
  • Server除了定义了一些get、set方法用于操作配置外,还定义了addService、findServices、removeService等方法用于操作Service对象,由此也可以看出Server和Serivce组件的关系。

Service

Service对应Tomcat源码中的org.apache.catalina.Service接口,其实现类为:org.apache.catalina.core.StandardService,继承关系如下图所示:

Service的继承关系与Server继承关系很相似,除自身定义的接口其他都是一样。StandardService部分源码如下:

// ----------------------------------------------------- Instance Variables
/**
* The name of this service.
*/
private String name = null;
/**
* The <code>Server</code> that owns this Service, if any.
*/
private Server server = null;
/**
* The set of Connectors associated with this Service.
*/
protected Connector connectors[] = new Connector[0];
/**
* The list of executors held by the service.
*/
protected final ArrayList<Executor> executors = new ArrayList<>();private Engine engine = null;

从源码中可以看到Service组件的内部结构

  • 持有Engine实例
  • 持有Server实例
  • 可以管理多个Connector实例
  • 持有Executor引用

Connector

Connector对应Tomcat源码中的org.apache.catalina.connector.Connector类,继承关系如下图所示:

Connector是Tomcat中监听TCP端口的组件,server.xml默认定义了两个Connector,分别用于监听http、ajp端口。

http监听配置

<Connector port="8080" protocol="HTTP/1.1"connectionTimeout="20000"redirectPort="8443" />

http对应的Connector配置如上所示,其中port用于指定监听端口;protocol用于指定http协议的版本,还可以支持2.0;connectionTimeout定义了连接超时时间,单位是毫秒;redirectPort是SSL的重定向端口,它会把请求重定向到8443这个端口

AJP监听配置

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Apache jserver协议(AJP)是一种二进制协议,它可以将来自web服务器的入站请求发送到位于web服务器后的应用服务器。如果我们希望把Tomcat集成到现有的(或新的)Apache http server中,并且希望Apache能够处理web应用程序中包含的静态内容,或者使用Apache的SSL处理,我们便可以使用该协议。但是,在实际的项目应用中,AJP协议并不常用,大多数应用场景会使用nginx+tomcat实现负载。

下面看一下Connector构造函数源码如下:

// ------------------------------------------------------------ Constructor/*** Defaults to using HTTP/1.1 NIO implementation.*/
public Connector() {this("org.apache.coyote.http11.Http11NioProtocol");
}public Connector(String protocol) {boolean aprConnector = AprLifecycleListener.isAprAvailable() &&AprLifecycleListener.getUseAprConnector();if ("HTTP/1.1".equals(protocol) || protocol == null) {if (aprConnector) {protocolHandlerClassName = "org.apache.coyote.http11.Http11AprProtocol";} else {protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";}} else if ("AJP/1.3".equals(protocol)) {if (aprConnector) {protocolHandlerClassName = "org.apache.coyote.ajp.AjpAprProtocol";} else {protocolHandlerClassName = "org.apache.coyote.ajp.AjpNioProtocol";}} else {protocolHandlerClassName = protocol;}// Instantiate protocol handlerProtocolHandler p = null;try {Class<?> clazz = Class.forName(protocolHandlerClassName);p = (ProtocolHandler) clazz.getConstructor().newInstance();} catch (Exception e) {log.error(sm.getString("coyoteConnector.protocolHandlerInstantiationFailed"), e);} finally {this.protocolHandler = p;}// Default for Connector depends on this system propertysetThrowOnFailure(Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"));
}

从构造函数中可以看到Tomcat实现了HTTP/1.1和AJP/1.3两种协议,而且每个协议都两种实现方式。默认协议是:HTTP/1.1。

Container

Container对应Tomcat源码中的org.apache.catalina.Container接口,该接口定义了容器的API,Container部分源码如下:

/*** 添加一个容器添加到当前容器*/
public void addChild(Container child);/*** 根据名称获取当前容器的子容器*/
public Container findChild(String name);/*** 获取当前容器所有子容器*/
public Container[] findChildren();/*** 删除当前容器指定的子容器*/
public void removeChild(Container child);

它包含四种不同的容器:

  • Engine,表示整个Catalina的servlet引擎
  • Host,表示一个拥有若干个Context的虚拟主机
  • Context,表示一个Web应用,一个context包含一个或多个wrapper
  • Wrapper,表示一个独立的servlet

Container是用来处理来自客户端的servlet请求,并且返回响应的对象。继承关系如下图:

Engine、Host、Context、Wrapper都有一个默认的实现类StandardXXX,均继承至ContainerBase。此外,一个容器还包含一系列的Lodder、Logger、Manager、Realm和Resources等。一个容器可以有一个或多个低层次上的子容器,并且一个Catalina功能部署并不一定需要全部四种容器。一个Context有一个或多个wrapper,而wrapper作为容器层次中的最底层,不能包含子容器。

Engine

Engine对应Tomcat源码中的org.apache.catalina.Engine接口,其实默认现类为:org.apache.catalina.core.StandardEngine,继承关系如下图所示:

Engine表示Catalina的Servlet引擎,如果使用了Engine的话,则它是Catalina的顶层容器,因此在StandardEngine的setParent()方法中直接抛出的异常。

/*** Disallow any attempt to set a parent for this Container, since an* Engine is supposed to be at the top of the Container hierarchy.** @param container Proposed parent Container*/
@Override
public void setParent(Container container) {throw new IllegalArgumentException(sm.getString("standardEngine.notParent"));}

Host

Host对应Tomcat源码中的org.apache.catalina.Host接口,其默认实现类为:org.apache.catalina.core.StandardHost,继承关系如下图所示:

Host定义了一个虚拟主机,正所谓虚拟主机,当然是可以用来部署应用程序的,Tomcat的Host也是如此。它在server.xml中定义了一个localhost的Host,应用根目录在webapps下面,默认是支持解压重新部署的。

<Host name="localhost"  appBase="webapps"unpackWARs="true" autoDeploy="true"><!-- SingleSignOn valve, share authentication between web applicationsDocumentation at: /docs/config/valve.html --><!--<Valve className="org.apache.catalina.authenticator.SingleSignOn" />--><!-- Access log processes all example.Documentation at: /docs/config/valve.htmlNote: The pattern used is equivalent to using pattern="common" --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"prefix="localhost_access_log" suffix=".txt"pattern="%h %l %u %t &quot;%r&quot; %s %b" /></Host>

Context

Context对应Tomcat源码中的org.apache.catalina.Context接口,其默认实现类为:org.apache.catalina.core.StandardContext,继承关系如下图所示:

Context代表一个独立的web应用,针对每个Context,tomcat都是使用不同的Classloader避免类冲突。如果我们希望使用一个自定义的目录作为部署路径的话,可以在server.xml中新增Context即可

【ZhoujEndless】至此!感觉您的阅读,如有任何问题,欢迎打扰!如有表述错误,劳烦指出!

参考资料:https://blog.csdn.net/dwade_mia/article/details/79051404

【Tomcat源码阅读】核心组件介绍(二)相关推荐

  1. (五)Tomcat源码阅读:Connector组件分析

    一.概述 因为Connector组件没有实现接口规范,因此我们直接对该类的方法进行分析即可. 二.源码阅读 阅读思路,我的阅读思路是这样的,大的类无非就是对小类的使用,因此我们想分析整体的一下架构的化 ...

  2. JDK1.8源码阅读系列之二:LinkedList

    本篇随笔主要描述的是我阅读 LinkedList 源码期间的对于 LinkedList 的一些实现上的个人理解,有不对的地方,请指出- 先来看一下 LinkedList 的继承图: 由于 Abstra ...

  3. Tomcat源码解读系列(二)——Tomcat的核心组成和启动过程

    声明:源码版本为Tomcat 6.0.35 前面的文章中介绍了Tomcat的基本配置,每个配置项也基本上对应了Tomcat的组件结构,如果要用一张图来形象展现一下Tomcat组成的话,整个Tomcat ...

  4. Tomcat 源码阅读记录(1)

    使用Ant 工具进行编译打包. 源码对应关系: SourceCode TargetPackage /bin /bin /conf /conf /java /lib/* /Modules 依赖包 /re ...

  5. Spring Boot Transactional注解源码阅读笔记(二)

      在源码笔记(一)中,我们留下了几个问题: Spring Boot是怎么扫描到我们的bean里面有 Transactional 这个注解,并且把 InfrastructureAdvisorAutoP ...

  6. BWA源码阅读笔记(二)索引文件amb/ann/pac文件是什么?

    高通量数据比对讲究的就是一个快和准,因此大部分软件都是用C语言实现.BWA是目前基因组序列比对最常用的工具,由于自我感觉已经入门C语言,为了提高自己的水平,因此开始从源码角度学习李恒大神开发的BWA工 ...

  7. Tomcat源码阅读---ServletContext.java(小白写作,持续更新)

    everybody,想我没,刚考完操作系统,我胡汉三又回来啦!!!掌声!!!鲜花!!!接着奏乐,接着舞!!!来个大的!不要说我不够意思,这个ServletContext读完的确是让我对于web程序有了 ...

  8. tomcat源码阅读之Server和Service接口解析

    tomcat中的服务器组件接口是Server接口,服务接口是Service,Server接口表示Catalina的整个servlet引擎,囊括了所有的组件,提供了一种优雅的方式来启动/关闭Catali ...

  9. tomcat源码阅读之StandardHost和StandardEngine

    StandardHost及UML类图: 1.StandardHost类是Host接口的默认实现:其继承自ContainerBase类,说明他也是一个容器类,既然是容器类,那肯定也有管道对象PipeLi ...

最新文章

  1. 实现 strStr()
  2. 面试官:你用过哪些JDK自带的命令行工具
  3. 一文读懂分布式架构知识体系(内含超全核心知识大图)
  4. 笔记-高项案例题-2019年下-人力资源管理-管理者权力-马斯洛需求理论-冲突管理...
  5. 使用python读取txt坐标文件生成挖空矿山_探矿批量
  6. Linux 内核源代码的目录结构
  7. PHP socket初探 --- 一些零碎细节的拾漏补缺
  8. Leetcode 224.基本计算器
  9. 极客大学架构师训练营 系统架构 消息队列 负载均衡 数据库备份 第10课 听课总结
  10. 学习开源硬件:开源IP,开源RISC-V与开源SoC等
  11. python隐藏窗口_python怎么隐藏界面?
  12. ulimit修改open files永久生效
  13. 人脸识别-多张人脸检测
  14. 如何用MathType编辑出积分符号
  15. 一个命令行整理软著代码
  16. windows10 扩容C盘空间
  17. makefile编写知识小结
  18. 《大明王朝1566》观后感
  19. 源码学习之LAMMPS的一个时间步是如何工作的
  20. Python__绘制动态时钟表

热门文章

  1. 网易员工对《阿凡达》的爆笑影评
  2. mqtt session保持 订阅消息_iOS MQTT 3 - 发送订阅消息以及发送过程
  3. 知识点梳理IR-808 Biotin,Biotin 808-IR,IR808 生物素,红外吸收染料修饰生物素
  4. 机房空调节能方案如何实施?
  5. [Beta阶段]第一次Scrum Meeting
  6. 三菱FX3U——ST编程CASE选择
  7. 解决系统下以管理员身份运行的程序接收不到拖放文件消息[WM_DROPFILES]问题的方法
  8. fileformat set
  9. s7300的db块详细说明_S7300中FB、FC和DB块的使用
  10. Office安装出错的解决方法,如“Microsoft Office Professional Plus 2013在安装过程中出错”。