深入剖析Tomcat原理

深入剖析Tomcat原理

一、 Tomcat源码部署和运行(intellij IDEA)
1、下载tomcat源码,以tomcat-8为例
链接: https://tomcat.apache.org/
深入剖析Tomcat原理_第1张图片
深入剖析Tomcat原理_第2张图片
2、源码部署到IDEA中

①创建新的空工程
深入剖析Tomcat原理_第3张图片
②解压源码压缩包到该工程的目录(目录名最好是非中文和非空格组成的)下
深入剖析Tomcat原理_第4张图片
③创建home文件,并将webapps和conf文件移入home文件中,目的是为了后期配置IDEA运行时参数时方便
深入剖析Tomcat原理_第5张图片
④新建pom.xml文件,在其中添加tomcat运行时依赖:
深入剖析Tomcat原理_第6张图片


<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.42‐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>2.3version>
                <configuration>
                    <encoding>UTF-8encoding>
                    <source>1.8source>
                    <target>1.8target>
                configuration>
            plugin>
        plugins>
    build>
 
    <dependencies>
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.12version>
            <scope>testscope>
        dependency>
        <dependency>
            <groupId>org.easymockgroupId>
            <artifactId>easymockartifactId>
            <version>3.4version>
        dependency>
        <dependency>
            <groupId>antgroupId>
            <artifactId>antartifactId>
            <version>1.7.0version>
        dependency>
        <dependency>
            <groupId>wsdl4jgroupId>
            <artifactId>wsdl4jartifactId>
            <version>1.6.2version>
        dependency>
        <dependency>
            <groupId>javax.xmlgroupId>
            <artifactId>jaxrpcartifactId>
            <version>1.1version>
        dependency>
        <dependency>
            <groupId>org.eclipse.jdt.core.compilergroupId>
            <artifactId>ecjartifactId>
            <version>4.5.1version>
        dependency>
       
    dependencies>
project>

⑤在这个空project项目新建maven项目:
深入剖析Tomcat原理_第7张图片
⑥新建完maven项目后,添加application(用来启动/调试这些源码)
深入剖析Tomcat原理_第8张图片
深入剖析Tomcat原理_第9张图片
找到**java/org.apache/catalina/startup/bootstrap(类)**点击完成添加(主要是这个类就是整个tomcat启动的类,其中包含main()方法)
这时有可能添加错误,因为没有导入jdk
深入剖析Tomcat原理_第10张图片
⑦不报错后设置运行时参数:
深入剖析Tomcat原理_第11张图片
深入剖析Tomcat原理_第12张图片
就是选择刚刚新建的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原理_第13张图片
⑨浏览器访问Tomcat会出现问题:
深入剖析Tomcat原理_第14张图片
原因:
在这里插入图片描述
解决:
搜索并找到这个ContextConfig类下的configureStart()方法
深入剖析Tomcat原理_第15张图片
在该方法中的webConfig()方法下添加:
context.addServletContainerInitializer(new JasperInitializer(), null)
目的是手动将JSP解析器初始化
深入剖析Tomcat原理_第16张图片
重新启动Tomcat问题解决
深入剖析Tomcat原理_第17张图片
二、不得不提的HTTP工作流程与DNS解析详细过程

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

三、Tomcat整体架构

1)Http服务器的执行逻辑的两种方法:
1、Http服务器接收请求,根据请求先做一个判断,找到对应的业务类执行具体业务逻辑,这种方法耦合度过高(不推荐)
深入剖析Tomcat原理_第18张图片
2、Http服务器不亲自调用业务类,而是直接把请求转发给tomcat,由tomcat去判断需要调用具体哪个类来执行业务操作。
显然第二种方法解耦合度比较好。
深入剖析Tomcat原理_第19张图片
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原理_第20张图片
连接器在tomcat中称为coyote
Coyote主要负责底层socket连接的接收与响应,接收到浏览器的请求后,构建并封装进request对象,最终再转换成servletRequest对象传递给容器
将协议的处理、io的相关等操作交给coyote,将具体业务逻辑的操作等交给容器
一个service可以有多个连接器coyote和一个容器,但它们都不能单独对外提供服务,两者结合为service后,一个service才能对外提供服务。

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

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

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

2)service中容器和连接器的整体地位
深入剖析Tomcat原理_第23张图片
从源码中也能看出来,是一一对应的,一个service中有很多组件,核心就是容器深入剖析Tomcat原理_第24张图片
catalina:这个包包含启动项、容器、连接器(整体)、公共类等
coyote:这个包包含连接器(connector)下的各个组件(protocolHandler、adapter、processor等)

3)service内部细节
深入剖析Tomcat原理_第25张图片
Contain(容器)具体结构详解:
深入剖析Tomcat原理_第26张图片
Engine(引擎):管理多个虚拟站点(虚拟主机),也是一个service只能有一个引擎。一个引擎可管理多个Host。一个Host可包含多个Context(项目),一个Context下包含多个Wrapper(servlet)

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

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

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

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

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

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

你可能感兴趣的:(tomcat,java,servlet,http)