Tomcat源码剖析笔记总结(超长干货——逐步分析)

主要分四部分:

  • 套娃式架构设计
    • 架构属于设计层次,源码是对设计的实现
    • Tomcat的架构设计比较独特,属于套娃式架构设计
  • 源码剖析的原则、方法和技巧
  • Tomcat实例构建(启动过程源码分析)
  • Servlet请求处理链路(Servlet如何被Tomcat处理的)

文章目录

    • @[toc]
  • 一、Tomcat架构设计
    • 1.1 Tomcat的功能(需求)
    • 1.2 Tomcat的架构(架构就是为了完成功能需求做的设计)
      • 1.2.1 架构解读
      • 1.2.2 架构与配置文件的对应
    • 1.3 Tomcat套娃式架构设计的好处
  • 二、源码剖析技巧
  • 三、Tomcat实例构建脉络
    • 3.1 源码构建方式
    • 3.2 启动过程源码剖析
      • 3.2.1 生命周期统一管理组件LifeCycle
      • 3.2.2 启动流程
      • 3.2.3 load初始化阶段
      • 3.2.4 start启动阶段
        • 3.2.4.1 Engine启动过程start源码分析
        • 3.2.4.2 Connector启动过程start源码分析
  • 四、Servlet请求处理链路
    • 4.1 Mapper组件体系结构
    • 4.2 mapper对象数据何时初始化的
    • 4.3 Servlet请求处理流程示意
    • 4.4 Servlet请求处理源码剖析

一、Tomcat架构设计

功能是从需求的角度进行描述的,架构是从设计的角度进行描述的,源码是从实现的角度进行描述的

1.1 Tomcat的功能(需求)

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第1张图片
Tomcat两个非常重要的功能(身份)

  • Http服务器功能:Socket通信(TCP/IP)、解析Http报文
  • Servlet容器功能:有很多Servlet(自带系统级Servlet+自定义Servlet),Servlet处理具体的业务逻辑

1.2 Tomcat的架构(架构就是为了完成功能需求做的设计)

1.2.1 架构解读

什么是Tomcat架构: 为了实现上述的功能,Tomcat进行了很多的封装设计,封装出了很多的组件(组件在源代码中的体现就是Java类),组件与组件之间的关系就构成了所谓的Tomcat架构。
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第2张图片
一个Service内部可以有多个Connector组件,因为一个Connector绑定一个端口进行监听,多个Connector可以监听多个端口,但是一个Service内部的多个Connector只能对应一个Servlet容器。

除了Connector组件和Container组件,Tomcat其实还定义了很多其他组件来工作(server-service-connector/container-engine-host-context-wrapper)。这些组件采用一层套一层的设计方式(套娃式),如果一个组件包含了其他组件,那么这个组件也称之为容器。

1.2.2 架构与配置文件的对应

conf目录下的server.xml文件:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第3张图片

  • Server:Server容器就代表一个Tomcat实例(Catalina实例),其下可以有一个或者多个Service容器;
  • Service:Service是提供具体对外服务的(默认只有一个),一个Service容器中又可以有多个Connector组件(监听不同端口请求,解析请求)和一个Servlet容器(做具体的业务逻辑处理);
  • Engine和Host:Engine组件(引擎)是Servlet容器Catalina的核心,它支持在其下定义多个虚拟主机(Host),虚拟主机允许Tomcat引擎在将配置在一台机器上的多个域名,比如www.baidu.com、www.bat.com分割开来互不干扰;
  • Context:每个虚拟主机又可以支持多个web应用部署在它下边,这就是我们所熟知的上下文对象Context,上下文是使用由Servlet规范中指定的Web应用程序格式表示,不论是压缩过的war包形式的文件还是未压缩的目录形式;
  • Wrapper:在上下文中又可以部署多个servlet,并且每个servlet都会被一个包装组件(Wrapper)所包含(一个wrapper对应一个servlet)。

1.3 Tomcat套娃式架构设计的好处

  • 一层套一层的方式,其实组件关系还是很清晰的,也便于后期组件生命周期管理
  • tomcat这种架构设计正好和xml配置文件中标签的包含方式对应上,那么后续在解读xml以及封装对象的过程中就容易对应
  • 便于子容器继承父容器的一些配置

二、源码剖析技巧

剖析源代码需要讲究一些原则,注意一些方法和技巧,否则很容易就在浩瀚的源代码海洋中迷失自己

好处:提高我们的架构思维、深入认识代码、深入理解一个项目/框架

原则:

  • 定焦原则:抓主线(抓住一个核心流程去分析,不要漫无目的的去看源代码)
  • 宏观原则:站在上帝的视角,先脉络后枝叶(切忌试图搞清楚看到的每一行代码)

方法和技巧

  • 断点(观察调用栈)
  • 反调(右键,Find Usages)
  • 经验之谈(比如一些doXXX,service()…往往都是具体干活的一些方法)
  • 见名思意(比如通过方法名称就可以联想到这个方法的作用)
  • 多多实际动手操练,灵活运用上述方法技巧

三、Tomcat实例构建脉络

3.1 源码构建方式

说明:

  1. 基于Tomcat8.5.54的源码进行说明
  2. 添加了一个web_demo应用在webapps中用于演示,该项目只有一个名为resumeservlet的servlet
  3. Tomcat本身就是Java开发的软件,直接使用Tomcat的时候,Tomcat需要读取server.xml以及其他的配置文件,同时还需要找到它要去部署的工程项目。使用源码方式,依然如此

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第4张图片

操作步骤:

步骤一:解压源码压缩包,得到目录apache-tomcat-8.5.54-src

下载地址:https://tomcat.apache.org/download-80.cgi

下载最下面的Source Code Distributions源码版本,我这里下载的是zip的

步骤二:进入apache-tomcat-8.5.54-src目录,创建一个pom.xml文件,文件内容如下:


<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.0modelVersion>
    <groupId>org.apache.tomcatgroupId>
    <artifactId>apache-tomcat-8.5.50-srcartifactId>
    <name>Tomcat8.5name>
    <version>8.5version>
 
    <build>
      	
        <finalName>Tomcat8.5finalName>
        <sourceDirectory>javasourceDirectory>
        <resources>
            <resource>
                <directory>javadirectory>
            resource>
        resources>
        <plugins>
          	
            <plugin>
                <groupId>org.apache.maven.pluginsgroupId>
                <artifactId>maven-compiler-pluginartifactId>
                <version>3.1version>
                <configuration>
                    <encoding>UTF-8encoding>
                    <source>11source>
                    <target>11target>
                configuration>
            plugin>
        plugins>
    build>

    
    <dependencies>
        
        <dependency>
            <groupId>javax.xmlgroupId>
            <artifactId>jaxrpcartifactId>
            <version>1.1version>
        dependency>
        
        <dependency>
            <groupId>javax.xml.soapgroupId>
            <artifactId>javax.xml.soap-apiartifactId>
            <version>1.4.0version>
        dependency>
        
        <dependency>
            <groupId>wsdl4jgroupId>
            <artifactId>wsdl4jartifactId>
            <version>1.6.2version>
        dependency>
        
        <dependency>
            <groupId>org.eclipse.jdt.core.compilergroupId>
            <artifactId>ecjartifactId>
            <version>4.5.1version>
        dependency>
        
        <dependency>
            <groupId>antgroupId>
            <artifactId>antartifactId>
            <version>1.7.0version>
        dependency>
        
        <dependency>
            <groupId>org.easymockgroupId>
            <artifactId>easymockartifactId>
            <version>3.4version>
        dependency>
    dependencies>
project>

步骤三:在apache-tomcat-8.5.54-src目录中创建source文件夹

步骤四:将conf、webapps目录移动到刚刚创建的source文件夹中

步骤五:将源码工程导入到IDEA中

IDEA中应当已经配置好Maven

步骤六:给tomcat的源码程序配置Run/Debug Configurations
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第5张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第6张图片Tomcat源码剖析笔记总结(超长干货——逐步分析)_第7张图片

注意这里要使用Java11,因为pom.xml中配置使用的是Java11

这里要给tomcat的源码程序启动类Bootstrap配置VM参数,因为tomcat源码运行也需要加载配置文件等

-Dcatalina.home=E:\Code\IdeaProjects\apache-tomcat-8.5.54-src/source
-Dcatalina.base=E:\Code\IdeaProjects\apache-tomcat-8.5.54-src/source
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=E:\Code\IdeaProjects\apache-tomcat-8.5.54-src/source/conf/logging.properties

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第8张图片
填写VM参数时根据自己tomcat源码项目放置位置进行更改

步骤七:Build项目,此时会报错
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第9张图片
找到错误位置,使用Alt+Enter第一条即可修复该问题,然后重新Build即可
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第10张图片
步骤八:运行项目就启动了tomcat,启动时会加载所配置的conf目录下的server.xml等配置文件,所以访问8080端口即可,但此时会遇到如下的一个错误:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第11张图片
原因是Tomcat源码中Jsp引擎Jasper没有被初始化,从而无法编译处理Jsp(因为Jsp是需要被转换成servlet进一步编译处理的),只需要在tomcat的源码ContextConfig类中的configureStart方法中增加一行代码将Jsp引擎初始化,如下
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第12张图片
步骤九:重启Tomcat,正常访问即可。至此,Tomcat源码构建完毕。

3.2 启动过程源码剖析

3.2.1 生命周期统一管理组件LifeCycle

Tomcat要启动,肯定要把架构中提到的组件进行实例化(实例化创建–>销毁等:生命周期)。Tomcat中那么多组件,为了统一规范他们的生命周期,Tomcat抽象出了LifeCycle生命周期接口

LifeCycle生命周期接口方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第13张图片
LifeCycle生命周期接口的继承体系:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第14张图片

3.2.2 启动流程

(1)启动入口分析

startup.sh --> catalina.sh start --> java xxxx.jar org.apache.catalina.startup.Bootstrap(main) start(参数)

(2)启动流程图
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第15张图片
(3)启动流程分析

① Bootstrap的main方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第16张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第17张图片
② Bootstrap的init方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第18张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第19张图片
经过前两步,设置了

catalinaDaemon = catalina对象

daemon = bootstrap对象

③ Bootstrap的load方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第20张图片
④ Bootstrap的start方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第21张图片

3.2.3 load初始化阶段

(1)流程图
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第22张图片
(2)源码分析

① Catalina的load方法:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第23张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第24张图片Tomcat源码剖析笔记总结(超长干货——逐步分析)_第25张图片

Server的init初始化:
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第26张图片

② Digester的parse方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第27张图片

得到的root变量内容:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第28张图片

server相关值:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第29张图片

service相关值:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第30张图片

engine相关值:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第31张图片

得到的内容与解析的server.xml文件配置内容一致

③ LifecycleBase的init方法(使用了设计模式的模板方法):

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第32张图片

此处的initInternal会跳转至实现该接口的具体类的对象中

④ StandardServer的initInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第33张图片

会跳转至service的init方法中,即继续调用service实现的Lifecycle的init方法

⑤ StandardService的initInternal方法:

分别初始化service中的容器部分和connector部分

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第34张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第35张图片

⑥ StandardEngine的initInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第36张图片

⑦ ContainerBase的initInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第37张图片

注:ContainerBase是StandardEngine、StandardWrapper、StandardContext和StandardHost的父类
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第38张图片

⑧ Connector的initInternal方法:

绑定适配器:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第39张图片

初始化protocolHandler组件:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第40张图片

⑨ AbstractProtocol的init方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第41张图片

⑩ AbstractEndpoint的init方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第42张图片

⑪ NioEndpoint的bind方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第43张图片

3.2.4 start启动阶段

(1)流程图

与load过程很相似

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第44张图片

(2)源码分析

① Catalina的start方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第45张图片

② LifecycleBase的start方法(同样使用了设计模式的模板方法):

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第46张图片

④ StandardServer的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第47张图片

⑤ StandardService的startInternal方法:

分别启动其中的engine和connector

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第48张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第49张图片

3.2.4.1 Engine启动过程start源码分析

① StandardEngine的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第50张图片

最后调用父类ContainerBase的startInternal方法

② ContainerBase的startInternal方法:

Engine调用它父类执行该方法时,子容器为Host:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第51张图片

将子容器Host提交到具体的StartChild线程类并行执行

注:该线程池只专门用来实例化Host

Host调用它父类执行该方法时,通过设置生命周期事件来进行实例化

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第52张图片

③ StartChild线程类:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第53张图片

④ StandardHost的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第54张图片

⑤ LifecycleBase的setStateInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第55张图片

⑥ LifecycleBase的fireLifecycleEvent方法:

触发Host的生命周期事件后,将后续工作交给生命周期监听器HostConfig来进行

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第56张图片

⑦ Hostconfig的lifecycleEvent方法:

捕获start事件,执行start方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第57张图片

⑧ Hostconfig的start方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第58张图片

⑨ Hostconfig的deployApps方法:

根据不同的应用部署方式,调用不同的方法

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第59张图片

⑩ Hostconfig的deployDirectories方法:

以线程方式并行处理多个项目:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第60张图片

⑪ DeployDirectory线程类:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第61张图片

⑫ Hostconfig的deployDirectory方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第62张图片

通过xml解析对象进行分析:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第63张图片

设置一些context应用的必要属性:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第64张图片

完善context的过程在addChild方法中

⑬ StandardHost的addChild方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第65张图片

⑭ ContainerBase的addChild方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第66张图片

⑮ ContainerBase的addChildInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第67张图片

⑯ StandardContext的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第68张图片

work目录存放jsp转换为servlet的中间过程临时文件

给每个应用设置类加载器:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第69张图片
关键步骤(把具体每个应用的处理交给了ContextConfig):

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第70张图片

查看已初始化的Servlet,其中两个为tomcat默认的servlet,另一个resumeservlet为自己的项目web_demo中的servlet:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第71张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第72张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第73张图片

由上图看出,此时只读取了servlet对应的类,但并未生成实例化对象。

loadOnStartup方法根据web.xml中配置servlet的load-on-startup来进行创建实例化对应servlet。执行之后,instance就有具体对象了。

load-on-startup大于0时在容器启动时加载,否则在第一次访问该servlet时加载

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第74张图片

⑰ StandardContext的loadOnStartup方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第75张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第76张图片

⑱ StandardWrapper的load方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第77张图片

⑲ StandardWrapper的loadServlet方法(实际实例化servlet的方法):

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第78张图片

3.2.4.2 Connector启动过程start源码分析

① Connector的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第79张图片

② AbstractProtocol的start方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第80张图片

③ AbstractEndpoint的start方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第81张图片

④ NioEndpoint的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第82张图片

Tomcat中的NIO模型:

(1) 获取请求的工作封装交给了Acceptor线程去完成

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第83张图片

(2) poller线程(下面分析servlet请求处理时的入口)

检查selector中是否有数据到来的channel,如果有就要进行处理

⑤ AbstractEndpoint的startAcceptorThreads方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第84张图片

⑥ NioEndpoint的createAcceptor方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第85张图片

⑦ Acceptor线程类中的run方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第86张图片

四、Servlet请求处理链路

一个servlet请求 --> 最终需要找到能够处理当前servlet请求的servlet实例 --> servlet.service()

4.1 Mapper组件体系结构

(1)结构图

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第87张图片

Tomcat中使用Mapper机制重新封装了Host-context-wrapper(servlet)之间的数据和关系。

在匹配出能够处理当前请求的对应Host、对应Context和对应Wrapper之前,mapper对象肯定已经初始化好了

(2)源代码结构

① Mapper类中有MappedHost数组,表示有多个Host

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第88张图片

② MappedHost中有一个ContextList

③ ContextList类中有MappedContext数组,表示该Host有多个Context

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第89张图片

④ MappedContext中有一个ContextVersion数组

⑤ ContextVersion中的MappedWrapper数组对应的就是servlet

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第90张图片

⑥ MappedHost、MappedContext和MappedWrapper都有一个MapElement基类

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第91张图片

4.2 mapper对象数据何时初始化的

StandardService --> startInternal --> mapperListener.start()中完成mapper对象初始化

(1)StandardService的startInternal方法:

基于已有信息数据完成Mapper对象的初始化

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第92张图片

此处的mapperListener也遵从统一的生命周期管理

(2)MapperListener的startInternal方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第93张图片

(3)MapperListener的registerHost方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第94张图片

此时的变量情况:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第95张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第96张图片

4.3 Servlet请求处理流程示意

(1)基本流程

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第97张图片

(2)详细流程

Poller线程是追踪入口

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第98张图片

4.4 Servlet请求处理源码剖析

(1) Poller的run方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第99张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第100张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第101张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第102张图片

(2)Poller的processKey方法:

在processSocket处设置断点:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第103张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第104张图片

(3)启动服务器,从浏览器发起访问请求

(4)AdstractEndpoint的processSocket方法:

把传入的socket交给一个线程进行处理

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第105张图片

(5)线程类SocketProcessorBase的run方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第106张图片

(6)SocketProcessor的doRun方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第107张图片
Tomcat源码剖析笔记总结(超长干货——逐步分析)_第108张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第109张图片

此处的getHandler为中间过程对象

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第110张图片

(7)ConnectionHandler的process方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第111张图片

取不到对应Processor的话

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第112张图片

仍没有则创建一个新的

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第113张图片

找到完成之后,使用其进行process

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第114张图片

此时的processor为Http11Processor,因为默认的http协议是1.1版本。它是用来解析Socket中的请求信息的

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第115张图片

(8)AbstractProcessorLight的process方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第116张图片

(9)Http11Processor的service方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第117张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第118张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第119张图片

此时获取得到的是CoyoteAdapter,连接器组件适配器

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第120张图片

(10)CoyoteAdapter的service方法:

传入的参数req和res是原生的Request和Response,第一步先进行适配转换

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第121张图片

转换完成后交给后面的Container中的具体组件处理,一层一层找到对应servlet,该流程对应了postParseRequest方法,即利用Mapper进行匹配查找,下面的(11)-(13)说明了这一过程

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第122张图片

匹配完成后调用下面的invoke逐级调用匹配的结果,下面的(14)-(22)说明了这一过程

(11)CoyoteAdapter的postParseRequest方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第123张图片

(12)Mapper的map方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第124张图片

(13)Mapper的internalMap方法进行具体的相关匹配:

分别根据name匹配host、context和mapper

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第125张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第126张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第127张图片

匹配到的结果存放在参数mappingData中(mappingDate就在request对象中):

  • 方法执行匹配前:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第128张图片

  • 方法执行返回后匹配到对应实例:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第129张图片

(14)StandardEngineValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第130张图片

(15)AbstractAccessLogValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第131张图片

(16)ErrorReportValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第132张图片

(17)StandardHostValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第133张图片

Request的gerContext方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第134张图片

继续深入调用context

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第135张图片

(18)AuthenticatorBase的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第136张图片

(19)StandardContextValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第137张图片

Request的getWrapper方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第138张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第139张图片

(20)StandardWrapperValve的invoke方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第140张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第141张图片

可以看到,执行完成后,得到的servlet即为对应的servlet

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第142张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第143张图片

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第144张图片

(21)ApplicationFilterChain的doFilter方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第145张图片

(22)ApplicationFilterChain的internalDoFilter方法:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第146张图片

此处是最终执行servlet中实际操作的部分!!

自己编写的ResumeServlet的内容

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第147张图片

  • 执行该行代码语句之前:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第148张图片

  • 执行该行代码语句之后:

Tomcat源码剖析笔记总结(超长干货——逐步分析)_第149张图片

你可能感兴趣的:(Java,源码阅读,web服务器)