深入剖析Tomcat原理

2023-11-05

深入剖析Tomcat原理

一、 Tomcat源码部署和运行(intellij IDEA)
1、下载tomcat源码,以tomcat-8为例
链接: https://tomcat.apache.org/
在这里插入图片描述
在这里插入图片描述
2、源码部署到IDEA中

①创建新的空工程
在这里插入图片描述
②解压源码压缩包到该工程的目录(目录名最好是非中文和非空格组成的)下
在这里插入图片描述
③创建home文件,并将webapps和conf文件移入home文件中,目的是为了后期配置IDEA运行时参数时方便
在这里插入图片描述
④新建pom.xml文件,在其中添加tomcat运行时依赖:
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>apache‐tomcat‐8.5.42‐src</artifactId>
    <name>Tomcat8.5</name>
    <version>8.5</version>
 
    <build>
        <finalName>Tomcat8.5</finalName>
        <sourceDirectory>java</sourceDirectory>
        <!-- <testSourceDirectory>test</testSourceDirectory>-->
        <resources>
            <resource>
                <directory>java</directory>
            </resource>
        </resources>
        <!--<testResources>
           <testResource>
                <directory>test</directory>
           </testResource>
        </testResources>-->
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.easymock</groupId>
            <artifactId>easymock</artifactId>
            <version>3.4</version>
        </dependency>
        <dependency>
            <groupId>ant</groupId>
            <artifactId>ant</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.2</version>
        </dependency>
        <dependency>
            <groupId>javax.xml</groupId>
            <artifactId>jaxrpc</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jdt.core.compiler</groupId>
            <artifactId>ecj</artifactId>
            <version>4.5.1</version>
        </dependency>
       
    </dependencies>
</project>

⑤在这个空project项目新建maven项目:
在这里插入图片描述
⑥新建完maven项目后,添加application(用来启动/调试这些源码)
在这里插入图片描述
在这里插入图片描述
找到**java/org.apache/catalina/startup/bootstrap(类)**点击完成添加(主要是这个类就是整个tomcat启动的类,其中包含main()方法)
这时有可能添加错误,因为没有导入jdk
在这里插入图片描述
⑦不报错后设置运行时参数:
在这里插入图片描述
在这里插入图片描述
就是选择刚刚新建的home目录路径
参数:
-Dcatalina.home=C:/Users/14047/IdeaProjects/tomcat-src/apache-tomcat-8.5.42-src/home
-Dcatalina.base=C:/Users/14047/IdeaProjects/tomcat-src/apache-tomcat-8.5.42-src/home
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=C:/Users/14047/IdeaProjects/tomcat-src/apache-tomcat-8.5.42-src/home/conf/logging.properties
注意

⑧以上设置无误后则可以启动
在这里插入图片描述
⑨浏览器访问Tomcat会出现问题:
在这里插入图片描述
原因:
在这里插入图片描述
解决:
搜索并找到这个ContextConfig类下的configureStart()方法
在这里插入图片描述
在该方法中的webConfig()方法下添加:
context.addServletContainerInitializer(new JasperInitializer(), null)
目的是手动将JSP解析器初始化
在这里插入图片描述
重新启动Tomcat问题解决
在这里插入图片描述
二、不得不提的HTTP工作流程与DNS解析详细过程

HTTP工作流程与DNS解析详解.

三、Tomcat整体架构

1)Http服务器的执行逻辑的两种方法:
1、Http服务器接收请求,根据请求先做一个判断,找到对应的业务类执行具体业务逻辑,这种方法耦合度过高(不推荐)
在这里插入图片描述
2、Http服务器不亲自调用业务类,而是直接把请求转发给tomcat,由tomcat去判断需要调用具体哪个类来执行业务操作。
显然第二种方法解耦合度比较好。
在这里插入图片描述
2)连接器+容器
Tomcat整体包含两大组件:连接器+容器 = service
这两大组件分别与之对应的是http服务器、servlet容器

1、 连接器:主要负责客户端浏览器传过来的请求+初始化request和response
2、 容器主要负责处理某个具体servlet的调用逻辑

浏览器发出请求----->连接器首先接收请求,构建request对象,在request对象构建中解析请求信息,封装相关属性(url、method…)。----->连接器将构建好的request对象传递给容器处理------->容器拿到request,根据request对象中的信息定位到哪个具体的servlet,并初始化且调用该servlet执行具体逻辑------>容器在调用某个servlet前已经将response对象构建好了,servlet执行完具体业务逻辑后,response对象中会包含响应数据,容器再将包含响应数据的response对象再响应回给连接器。------>连接器解析完response后再响应给浏览器

四、Tomcat整体架构——连接器(Coyote)与容器初讲
在这里插入图片描述
连接器在tomcat中称为coyote
Coyote主要负责底层socket连接的接收与响应,接收到浏览器的请求后,构建并封装进request对象,最终再转换成servletRequest对象传递给容器
将协议的处理、io的相关等操作交给coyote,将具体业务逻辑的操作等交给容器
一个service可以有多个连接器coyote和一个容器,但它们都不能单独对外提供服务,两者结合为service后,一个service才能对外提供服务。

一个service至少包含一个连接器和容器。
通过service接口就可看出其对应关系
向Service中添加Connector,可以是数组(add……)
在这里插入图片描述
给service设置一个容器只能是一个(set……)
在这里插入图片描述
连接器组件coyote的内部细节

1)连接器组件coyote的内部细节:

在这里插入图片描述
一个连接器中包含了四个组件:EndPoint、Processor、Adapter、ProtocolHandler
客户端浏览器发送请求至EndPoint(通信端点(专门用来接收发送过来的socket请求)),
EndPoint处理完后将请求又发送给处理器Processor,Processor将请求按照HTTP协议格式进行解析,拆封并封装成request对象。
对容器来说它只支持servletRequest规范,而对Processor来说它只提供Request,这时就需要用到适配器组件,将Request转换为servletRequest。

2)service中容器和连接器的整体地位
在这里插入图片描述
从源码中也能看出来,是一一对应的,一个service中有很多组件,核心就是容器在这里插入图片描述
catalina:这个包包含启动项、容器、连接器(整体)、公共类等
coyote:这个包包含连接器(connector)下的各个组件(protocolHandler、adapter、processor等)

3)service内部细节
在这里插入图片描述
Contain(容器)具体结构详解:
在这里插入图片描述
Engine(引擎):管理多个虚拟站点(虚拟主机),也是一个service只能有一个引擎。一个引擎可管理多个Host。一个Host可包含多个Context(项目),一个Context下包含多个Wrapper(servlet)

通过server.xml就可以看出其中的层次关系与上描述相符
在这里插入图片描述
通过源码分析看出
容器中包含着这四个组件
在这里插入图片描述
五、Tomcat源码基础上深入分析启动流程
Tomcat启动时序图:
在这里插入图片描述
1、用户点击startup.bat即可启动tomcat
在这里插入图片描述
Startup.bat文件中的具体细节:
在这里插入图片描述
其中调用了catalina.bat这个文件
在这里插入图片描述
catalina.bat这个文件中又调用了bootStrap类中的main()方法来开启整个tomcat的启动
在这里插入图片描述
六、上手Debug 源码跟踪Tomcat各个步骤

明确tomcat入口点为BootStrap类中的main()方法:
Startup.bat—>Catalina.bat---->Bootstrap.main()
1、Application让Bootstrap.main()方法启动,此方法一启动Bootstrap类的静态属性先初始化
在这里插入图片描述
在这里插入图片描述
//获取到home文件目录
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
2、初始化完静态变量后来到main()方法体:
构建BootStrap,给非静态属性赋初值null
在这里插入图片描述
在这里插入图片描述
3、bootstrap.init()方法执行,初始化Bootstrap
在这里插入图片描述
①初始化类加载器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
② 反射创建Catalina(容器)组件
在这里插入图片描述
Catalina组件的配置是依靠配置文件(server.xml)
在这里插入图片描述
最后init()方法结束,Catalina组件成功构建
在这里插入图片描述
初始化完成之后继续往下走:

③ 调用load方法:
匹配命令参数(“start”)
在这里插入图片描述
bootstrap调用load()方法
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从以上可以看出:BootStrap的load()方法主要功能就是去调用Catalina组件的load方法。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述Server.xml配置文件解析的相关设置完成,返回digester
在这里插入图片描述
在这里插入图片描述
Parse这一步是核心,因为这里在解析server.xml配置文件的同时时已将server接口的一个实现类创建出来(standardServer),并依据配置文件中的值,给standardServer的各个属性设置好相应的值,其中就包括services数组等
Parse前:
在这里插入图片描述
Parse后:
在这里插入图片描述

services(Server)中只有一个名为Server01的service
server.xml
在这里插入图片描述
这些组件在这一步只是依照server配置文件的配置项被构建出来,但组件中的一些必须的初始化还是要等到后续的init()方法完成。

④ 创建完Server后开始进行初始化init()
在这里插入图片描述
这里getServer()拿到Server,实现Server接口的是standardServer类
在这里插入图片描述
在这里插入图片描述
Server.init()根据多态,调用standardServer的init方法,standardServer无init()方法,根据继承默认调用父类 LifecycleMBeanBase的init()方法,发现LifecycleMBeanBase也无此方法
在这里插入图片描述
,则又去默认调用父类LifecycleBase的init()方法,诶发现有
在这里插入图片描述
则执行init()方法中的具体逻辑(this=standardServer,this.super.super.init()),其中又有initInternal()方法执行,此方法为抽象方法,standardServer中已实现,this.super.super.initInternal()调用时传的是this也就是standardServer,所以又跑回去执行standardServer中initInternal()方法具体逻辑
initInternal()方法中核心点就是对services数组中的每一个service进行初始化:
在这里插入图片描述
*(LifecycleMBeanBase类实现了LifeCycle接口,并抽取且提供了一些相同的代码功能,standardServer继承此类,重写相应方法,其它配置直接调用父类方法即可(模板思想)。)

⑤ 初始化每个service时同样利用多态思想,与server的初始化大致相同
在这里插入图片描述
This.super.super.init()方法初始化,其中initInternal()传递this,调用standardService的
在这里插入图片描述
引擎等都属于容器范畴,所以又多继承了一层containerBase
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
也就是:this.super.super.super.init(),同样的其中initInternal()还是回到StrandardEngine类中
在这里插入图片描述
引擎(Engine)初始化完毕。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入剖析Tomcat原理 的相关文章

随机推荐

  • @ApiModelProperty注解

    ApiModelProperty 用于方法 字段 表示对model属性的说明或者数据操作更改 value 字段说明 name 重写属性名字 dataType 重写属性类型 required 是否必填 example 举例说明 hidden
  • 电脑视频显示服务器运行失败,抖音直播伴侣提示:服务器终点无法运行操作或者创建视频源失败请重试解决方法视频教程...

    1 抖音直播伴侣多开 如果提示 服务器终点无法运行操作 或者创建视频源失败 请重试 多开插件一般是操作系统不兼容 要换操作系统 或者安装虚拟机 我推荐的操作系统是WIN10 64位 我拿了100多个操作系统测试 最终这个版本的稳定 可用 大
  • 图像分割套件PaddleSeg全面解析(四)数据预处理

    本部分主要介绍一下数据增强部分 PaddleSeg套件里把数据增强部分都定义在transforms里面 与Pytorch比较类似 这样就把一些基本的图像处理方法 缩放 归一化等 和数据增强 随机裁剪 翻转 颜色抖动 统一了 自己新增的数据增
  • 编程15年40岁程序员的我终于在压力下被迫转行了

    本人今年40岁多了 中山大学计算机小硕 已经从事it工作15年多 最后一次工作是2017年 创业 互联网教育方向 2020年失败关闭公司 创业失败后 在家沉淀了几个月 然后决定再次找工作 前几年频繁接到猎头电话的我 海投了不少公司 结果都渺
  • Linux网络协议栈

    TCP与UDP区别 区别一 是否基于连接 TCP是面向连接的协议 而UDP是无连接的协议 即TCP面向连接 UDP是无连接的 即发送数据之前不需要建立连接 区别二 可靠性 和 有序性 区别 TCP 提供交付保证 Tcp通过校验和 重传控制
  • mysql 控制每次批量插入5w条记录思路

    http blog csdn net jianjun4833 article details 71170113 由于业务中使用到word分词 所以数据量比较大 需要把分出来的结果插入到数据库 每次插入1条的话 非常慢 所以使用批量插入 具体
  • 【OpenCV】中copyto()函数的使用方法理解

    使用copyTo函数可以得到一个复制的矩阵 A copyTo B 就可以得到和A一模一样的矩阵B 当然需要事先声明B copyTo还有一个重构函数copyTo B MASK 意思是可以得到一个附加掩膜MASK的矩阵B 3 加载掩模 必须是灰
  • 有趣的python小程序-分贝测量

    声音是我们日常生活中非常重要的一种感官刺激 但长期受到高分贝噪音的干扰会对人体产生很大的伤害 因此 分贝 decibel dB 测量成为了一个重要的领域 其可以用来衡量声音的强度和能量 在本篇博客中 我们将介绍如何使用 Python 编写一
  • Mysql最常用时间格式转化

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 1 Date转字符串 2 字符串转Date 3 上述转化的字符串格式有许多种 常见的几种如下 总结 前言 主要介绍了Mysql中最常用的两个时间格式转化函数
  • 最简单的打印数组的方式

    注意 输出数组 不用 System out println arr toString System out println arr 以上两种方法输出的是数组的地址 下面这种方法输出的才是数组的内容 System out println Ar
  • 数据库课程设计 医院管理系统 SQL

    文章目录 一 背景资料 需求分析 二 功能模块 三 功能设计说明书 要求详细描述各模块功能 给出模块结构图 SC图 四 数据库设计 1 概念模型 图 2 逻辑模型 五 建表以及sql语句 1 病人表 2 医生表 3 科室表 4 病房表 六
  • JDBC连接Mysql长时间无动作连接失效

    错误场景介绍 做的有一个项目使用JDBC手动创建Connection实现了一个简单的自定义数据库连接池 用来支持Canal解析数据库Binlog指定业务库的插入修改SQL来进行数据库分表备份 按照月份 操作 但是发现当一个一段时间 较长 没
  • 零基础ros基于arduino键盘控制小车(2)

    1上传下位机程序 上传成功后 打开窗口监视器 输入m 20 20来进行测试 e键来检测编码器的值 r键复原 调试的过程在这里便不废话了 2上传上位机程序 2 1 见网上大多数是输入以下指令来查看当前可用窗口 ls dev tty 我是直接打
  • Error 11 No resource identifier found for attribute 'textAlignment' in package 'android' 问题解决

    遇到这个问题是因为最近在做融云及时通讯 当导入moudle后 在编译就出现了这个问题 刚开始在百度上搜 提示要把target api level 改为19 改完之后还是报同样的错误 然后就认为不是这个地方的原因 在别的地方找了好久也没找到
  • 【图文详解】入职必备——SVN使用教程

    一 SVN基本操作 1 进入svnbucket官网 创建一个空项目 学习svn 2 创建好测试项目后 复制对应地址 3 右键点击 SVN 检出 4 粘贴 版本库URL 填写 检出至目录 最后点击 确定 5 完善 用户名 和 密码 同svnb
  • SpringBoot系列--自定义Starter

    提到Spring Boot时 很多人想到的是它的自动化装配特性 当我们项目需要Redis MongoDB时 只需要引入相应的 spring boot starter data redis spring boot starter data m
  • log库spdlog简介及使用

    spdlog是一个开源的 快速的 仅有头文件的C 11 日志库 code地址在 https github com gabime spdlog 目前最新的发布版本为0 14 0 它提供了向流 标准输出 文件 系统日志 调试器等目标输出日志的能
  • 程序员常用在线工具网址

    online tools 1 字符串长度计算 https www toolbaba cn d dev str count 2 在线sha加密工具 http tools jb51 net password sha encode 3 在线进制转
  • Opencv通过颜色区分电线

    Opencv检测不同颜色的电线是否接好 机器视觉检测物体要根据检测对象的特征找到最方便快捷的方法 最近做了一个靠颜色像素来区分电线的小项目 颜色区分是inRange方法 这个方法检测的是HSV彩色图像的范围 需要将图像转换为HSV图像 如图
  • 深入剖析Tomcat原理

    深入剖析Tomcat原理 一 Tomcat源码部署和运行 intellij IDEA 1 下载tomcat源码 以tomcat 8为例 链接 https tomcat apache org 2 源码部署到IDEA中 创建新的空工程 解压源码