转自-视频地址:JavaWeb开发必看!Tomcat架构及工作原理(8分钟)_哔哩哔哩_bilibili

Tomcat 目录结构

  • bin目录下存放的是可执行的二进制文件,其中startup.bat文件是用来启动服务器的,shutdown.bat则用于停止服务器
  • config文件夹下面是一些配置文件,其中server.xml文件存放着一些服务器的关键配置信息
  • lib目录下是一些jar 包
  • webapp目录存放的是一台主机的网站内容,需要特别注意的是:这里说的主机并非一台电脑,而是指一台Tomcat 管理的虚拟主机,

Tomcat 架构及工作原理_核心架构

通常,我们在浏览器的地址栏中输入地址的第一部分就是虚拟主机的名字,在这个意义上说域名就是虚拟主机的名字,每一台虚拟主机的内容都存放与自己的文件夹,正因为它仅仅是一个文件夹,而不是一台真正的电脑,所以被称为虚拟主机,也就再正常不过了。

我这台电脑的Tomcat 管理了两台虚拟主机,一台虚拟主机的名字叫“localhost”,它对应的文件夹是“webapps”;

Tomcat 架构及工作原理_Tomcat_02

另一台虚拟主机的名字叫“captainjack”,它对应的文件夹是“wptwebapps”

Tomcat 架构及工作原理_核心架构_03

到这里,你是否会有点好奇?我一台电脑只有一个IP,采用的都是8080 端口,为什么能够挂两个网站?

Tomcat 架构及工作原理_工作原理_04

Tomcat 架构及工作原理_工作原理_05

他们真的是两个独立的网站。要理解这个问题,就要求我们掌握Tomcat 的核心框架,以及工作原理。

核心框架及工作原理

我们先打开conf 目录下的关键配置文件server.xml 

Tomcat 架构及工作原理_工作原理_06

为了便于分析,这里截取它的核心内容:

Tomcat 架构及工作原理_工作原理_07

这是一个树形目录,根节点是server,server 就是这只猫所对应的类,它只会被实例化一次

Tomcat 架构及工作原理_工作原理_08

server节点下面可以包含多个service 节点,但通常我们只有一个,它的名字叫“Catalina”

Tomcat 架构及工作原理_核心架构_09

顾名思义,service 这个类或者说这个组件的作用,就是对外提供服务

Tomcat 架构及工作原理_Tomcat_10

service 内部又包含一组连接器和一个引擎,连接器负责通信,引擎则负责请求的处理

Tomcat 架构及工作原理_核心架构_11

在配置文件当中需指定连接器的监听端口,以及所采用的通信协议

Tomcat 架构及工作原理_工作原理_12

在默认情况下,采用HTTP 协议的连接器的监听端口是80 端口,采用HTTPS 协议的连接器监听端口是443 端口

Tomcat 架构及工作原理_工作原理_13

连接器的主要功能包括:

  • 监听网络端口
  • 接收网络请求
  • 读取请求中的网络字节流
  • 根据通信协议对网络字节流进行划分,对各元素进行识别,并将请求字节流转换成request 对象
  • 接着以request对象为参数,调用Servlet 容器,也即是这个引擎(Engine),引擎处理完请求信息后,返回一个response 对象
  • 连接器再将response 对象中的元素转换成响应字节流
  • 将响应字节流发给浏览器

Tomcat 架构及工作原理_核心架构_14

引擎是一个容器,里面包含一个或多个host 对象,也即虚拟主机

Tomcat 架构及工作原理_工作原理_15

在配置文件中,应该指定虚拟主机的主机名,以及它的内容所存放的文件夹

Tomcat 架构及工作原理_Tomcat_16

这台电脑的Tomcat 配置了两台虚拟主机,

Tomcat 架构及工作原理_Tomcat_17

从配置文件可以看出,这里包含两台虚拟主机,它们的主机名分别为“localhost”和“www.captainjack.com”

主机对应的文件夹分别为“webapps”和“wptwebapps”

为了使得浏览器在输入“www.captainjack.com”主机名时访问本机的ip 地址,我们通过修改windows 系统下的hosts 文件,在本地进行域名解析:

Tomcat 架构及工作原理_核心架构_18

Tomcat 架构及工作原理_Tomcat_19

这样一来,无论是输入这个主机名,还是localhost 主机名,他们都会被解析成ip 地址“127.0.0.1”,也即是本机ip 地址,也就是说浏览器通过相同的ip 地址和相同的端口号访问到了不同的虚拟主机,这是怎么做到的呢?

Tomcat 架构及工作原理_Tomcat_20

有一条线索很重要,通过网络抓包可以发现,浏览器发出的HTTP 请求消息里面,包含有要访问的主机名

Tomcat 架构及工作原理_核心架构_21

Tomcat 架构及工作原理_Tomcat_22

请求消息里面的主机名,又被连接器识别出来,并且放到了request 对象里面,引擎根据request 对象里面的目标主机名将request 对象派发给相应的主机来处理,这就是一台电脑能够同时部署多个网站的原因

Tomcat 架构及工作原理_Tomcat_23

Tomcat 架构及工作原理_工作原理_24

一台虚拟主机上通常又挂着多个应用,一个应用对应一个Context 对象,在配置文件里,需要将应用作为主机的子节点,配置应用节点Context 的时候有两个关键参数:一个是“docBase”,它的值应该是应用文件夹所在的物理地址,还有一个是“path”,它对应的是应用所对应的URL 地址

Tomcat 架构及工作原理_核心架构_25

我这台电脑localhost 主机上面挂载的两个应用,它们的访问路径分别是“webFirst”和“webSecond”,我们来试一下:

Tomcat 架构及工作原理_Tomcat_26

大家注意一下这两个URL 地址,它们的第一部分相同,但第二部分是用来区分不同的应用的

同时注意到localhost 主机它的文件夹是webapps,它下面挂载了两个应用文件夹,一个是“webFirst”,一个是“webSecond”

Tomcat 架构及工作原理_核心架构_27

Tomcat 架构及工作原理_工作原理_28

通常一个应用又包含多个不同的servlet,每一个servlet 可以有一个或多个实例,同一个servlet 的所有实例被放在容器“Wrapper”中进行管理。在这里,Engine、Host、Context、Wrapper 都是容器,通过这些容器,电脑上的servlet 被进行了详细的分类管理,连接器给出的request 请求对象里面包含了他要访问的servlet 的详细路径,具体来说就是主机名/应用名(路径)/servlet名(路径),都可以在request 对象里面找到,所以各级容器收到了对象之后,就能把它正确地派发给下一级容器,最后到达目标servlet 对象。这个request 对象的层层转发过程,本质上就是函数的层层调用过程,这个调用过程完成之后,连接器将得到一个response 对象,连接器再将response 对象转换为字节流返回给浏览器,这就是Tomcat 的核心架构和工作原理。