tomcat源码阅读(一) 源码下载 启动

下载源码

https://tomcat.apache.org/download-80.cgi
在这里插入图片描述

解压

解压以及创建必要目录和配置
解压、新建catalina-home目录,同时将目录中的conf和webapps文件夹复制到catalina-home目录中
在这里插入图片描述

在根目录新建pom.xml

<?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>Tomcat8.5</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>

IDEA 导入maven项目

在这里插入图片描述

启动

在这里插入图片描述
还需要添加vm参数

-Dcatalina.home=catalina-home
-Dcatalina.base=catalina-home
-Djava.endorsed.dirs=catalina-home/endorsed
-Djava.io.tmpdir=catalina-home/temp
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=catalina-home/conf/logging.properties

在这里插入图片描述

启动报错

Error:osgi: [Tomcat8.5] Invalid value for Bundle-Version, @VERSION@ does not match [0-9]{1,9}(\.[0-9]{1,9}(\.[0-9]{1,9}(\.[0-9A-Za-z_-]+)?)?)?

在这里插入图片描述
修改 @VERSION@ 为 8
在这里插入图片描述

第二个报错

Test测试代码报错,注释该代码即可。Tomcat源码util.TestCookieFilter类会报错,将其注释即可

启动

127.0.0.1:8080(乱码忽略)(已解决,参照
在这里插入图片描述
原因是我们直接启动org.apache.catalina.startup.Bootstrap的时候没有加载org.apache.jasper.servlet.JasperInitializer,从而无法编译JSP。

解决办法是在tomcat的源码org.apache.catalina.startup.ContextConfig中的configureStart函数中手动将JSP解析器初始化:

添加代码:context.addServletContainerInitializer(new JasperInitializer(), null);

添加位置如下图:
在这里插入图片描述

再次启动

在这里插入图片描述

tomcat 启动流程

在这里插入图片描述

tomcat 组件生命周期

             start()
   -----------------------------
   |                           |
   | init()                    |
  NEW -»-- INITIALIZING        |
  | |           |              |     ------------------«-----------------------
  | |           |auto          |     |                                        |
  | |          \|/    start() \|/   \|/     auto          auto         stop() |
  | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
  | |         |                                                            |  |
  | |destroy()|                                                            |  |
  | --»-----«--    ------------------------«--------------------------------  ^
  |     |          |                                                          |
  |     |         \|/          auto                 auto              start() |
  |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
  |    \|/                               ^                     |  ^
  |     |               stop()           |                     |  |
  |     |       --------------------------                     |  |
  |     |       |                                              |  |
  |     |       |    destroy()                       destroy() |  |
  |     |    FAILED ----»------ DESTROYING ---«-----------------  |
  |     |                        ^     |                          |
  |     |     destroy()          |     |auto                      |
  |     --------»-----------------    \|/                         |
  |                                 DESTROYED                     |
  |                                                               |
  |                            stop()                             |
  ----»-----------------------------»------------------------------

tomcat请求过程以及框架图

https://www.processon.com/view/5e79a432e4b06b852ff2e4f9#map

框架图

在这里插入图片描述

请求过程

在这里插入图片描述

链接器(Connector)与容器(Container)

Connector(高内聚、低耦合)

1、Endpoint提供Socket字节流给Processor
2、Porcessor提供Tomcat Request对象给Adapter
3、Adapter 提供ServletRequest给Container
图解:
Endpoint接收Socket连接,生成一个SocketProcessor任务提交到线程池去处理
SocketProcessor的run方法会调用Processor组件去解析应用层协议,Processor通过解析生成Request对象后,会调
用Adapter的service方法
在这里插入图片描述

Container

Container处理请求是使用Pipeline-valve管道来处理的.Pipeline-valve是责任链模式,区别于普通的责任链:
(1)每个Pipeline都有特定的valve,而且是在管道的最后一个执行,这个valve叫做BaseValve,BaseValve是不可删除的;
(2)在上层容器的管道的BaseValve中会调用下层容器的管道。

我们知道Container包含四个子容器,而这四个子容器对应的BaseValve分别在:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve

  • Container中的Pipeline在抽象实现类ContainerBase中定义,并在生命周期的startInternal,stopInternal,destroyInternal方法中调用管道的相应生命周期方法.
  • Pipeline调用所包含Valve的invoke方法来处理请求,并且在BaseValve里又调用了子容器Pipeline所包含Valve的invoke方法,直到最后调用了Wrapper的Pipeline所包含的BaseValve—StandardWrapperValve
    在这里插入图片描述

参考

https://www.cnblogs.com/Soy-technology/p/11223604.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值