Tomcat源码分析
Posted 踩踩踩从踩
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat源码分析相关的知识,希望对你有一定的参考价值。
前言
本篇文章 会针对tomcat的实现原理,以及servlet Tomcat容器与运行机制,利用servlet的规范实现的一套web服务器,而spring mvc 也是 spring实现了servlet 的web应用程序。 tomcat这么流行 的Servlet Web容器,具有大量的配置可以扩展 良好的运行效果,在开发中不应该只是会用,更重要的是对原理以及实现方式的理解,也许最后你也能写出很好的一个tomcat框架,也是为什么去研究他的原因。
Tomcat介绍
Tomcat 实现了 Java Servlet , JavaServer Page , Java 表达式语言和 Java 的 WebSocket 技术的一个开源实 现。说白了就是一个非常流行的Servlet Web 容器。Apache Tomcat®软件是Jakarta Servlet,Jakarta Server Pages,Jakarta Expression Language,Jakarta WebSocket,Jakarta Annotations和Jakarta Authentication规范的开源实现。这些规范是 Jakarta EE 平台的一部分.
Jakarta EE 平台是 Java EE 平台的演变。Tomcat 10 及更高版本实现了作为 Jakarta EE 的一部分开发的规范。Tomcat 9 及更早版本实现了作为 Java EE 的一部分开发的规范。
在9.0.40 根据 不同的安装包去下载不同的安装包。
下载过后 的关键目录
1. lib Tomcat 依赖的 jar 包 2. logs catalina-xxx.log localhost-xxx.log 3. webapps web 应用部署目录, eclipse 中的配置演示在bin目录中 包括的 bat 文件启动的 对应的 win版本的启动以及 linux的启动方式。
我们要开发中间件 都参考这种形式去开发就可以了。
config目录 这里面 的web.xml 以及 catalina.policy 设置运行jvm的 权限 等参数 都放到 这里面。
在 policy 中 包括了 shutdown 以及 juc日志等。
![](https://image.cha138.com/20221126/f513ea59a0b14a2da61d89692459c427.jpg)
![](https://image.cha138.com/20221126/1067b7e85fa940c4b47ae42d460ffad6.jpg)
执行器 线程池,重新定义 数量等等。
![](https://image.cha138.com/20221126/c107b031d47d497cae956477b1bec35a.jpg)
![](https://image.cha138.com/20221126/8a520a94e18b4aee99d7bde06aac4ea9.jpg)
![](https://image.cha138.com/20221126/d774e5ee9a244db4a9845ff7da866dec.jpg)
对于jsp 的请求访问 处理 方式等。
在 web.xml中可以 设置的json,能够解读 对应的映射地方 在 tomcat中 自动给我们设置好的。
tomcat-users.xml 配置相关的权限等。配置方式 在 文件上 都有一个例子给我们使用。
然后以及经常使用的地方也就是 webapps 启动 到 对应的 项目上
在使用上可以配置 对应 的访问地址,这都是tomcat提供给我们进行项目地址
jmx是jdk给我们提供的管理插件的功能,
部署方式
显式部署 1. 添加 context 元素方式 (server.xml)<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Context path="/Demo1" docBase="d:/Demo1" reloadable="true"></Context>
</Host>
2.
创建
xml
的方式
在
conf/Catalina/localhost
目录创建的
xml
文件
<?xml version="1.0" encoding="UTF-8"?>
<Context docBase="d:/Demo1" reloadable="true"></Context>
能访问到其他目录下面。
隐式部署
将一个
war
文件或者整个应用程序复制到
Tomcat
的
webapps
Tomcat源码下载与构建
IDE 装载 Tomcat 项目源码 Apache Tomcat 9 (9.0.60) - Building Tomcat需要添加 环境变量这些。
Tomcat 体系结构 Apache Tomcat 9 Architecture (9.0.60) - Table of ContentsTomcat容器与运行机制
Tomcat 启动步骤 Tomcat 的启动方式有下面几种方式: 1. 通过命令行启动 2. 通过 Java 程序,作为一个内嵌服务启动 3. 作为 windows 服务自动启动 bootstrap 作为启动类,![](https://image.cha138.com/20221126/1400a03fa6f34e018ddeec9c828e829e.jpg)
赋值catlina.bat 调用格式, start参数, 其实 start.bat 调用时,都是调用的catalina.bat,这个可以在脚本中就可以看出来
![](https://image.cha138.com/20221126/c9405e8c76664b28bf567d6dd7e071d6.jpg)
![](https://image.cha138.com/20221126/0774aec82fb349b190a18cf7dc741077.jpg)
![](https://image.cha138.com/20221126/c01c3cb3d8e5496da8af3969c2a9772f.jpg)
在tomcat中 的启动类
对于参数来说, 传入的参数 第一个参数就是 start
启动 最终底层 都调用到了bootstarp
做了初始化的操作 init
继续 加载 catalina
紧接着 继续下去
根据不同的 命令 选择 不同的方式进行方式。
然后继续下去 就是 初始化 命名 ,
设置命名空间等等。 初始化的factroy
解析 对应的serverxml 并设置 home 的file
创建 摘要器等 初始化部分。
- 1. 启动类加载器
- 2. 加载启动类
- 3. Bootstrap的守护线程初始化方法执行完成
1. Catalina.setAwait(true)
2. Catalina.load()
- 1. initDirs()方法设置属性值,例如
catalina.home = D:/tomcat
catalina.base == catalina.home
- 2. initNaming初始化命名
setProperty ( javax . naming . Context . INITIAL_CONTEXT_FACTORY , org . apache . naming . java . javaURLContextFactory - > default )
- 3. createStartDigester()
- 4. 加载server.xml并解析
- 5. 日志输出处理
- 6. 调用所有的组件初始化方法,确保每个对象都注册到了JMX代理上
3. Catalina.start()
1. 启动NamingContext绑定所有JNDI引用到NamingContext中
2. 启动<Server>标签下的service
3. 通过Service启动StandardHost
- 配置ErrorReportValve以对不同的HTTP错误代码执行正确的HTML输出
- 启动管道中的阀门Valve(至少是ErrorReportValve)
- 配置StandardHostValve
- 启动HostConfig组件
4. Tomcat 在HTTP端口上开始接受请求
5. Servlet类调用
Tomcat处理请求的过程
![](https://image.cha138.com/20221126/b87016c9f25c46e186aee05253d8aff2.jpg)
- 1. 用户点击网页内容,请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector获得。
- 2. Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
- 3. Engine获得请求localhost/test/index.jsp,匹配所有的虚拟主机Host。
- 4. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机),名为localhost的Host获得请求/test/index.jsp,匹配它所拥有的所有的 Context。Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为“ ”的Context 去处理)。 path=“/test”的Context获得请求/index.jsp,在它的mapping table中寻找出对应的 Servlet。Context匹配到URL PATTERN为*.jsp的Servlet,对应于JspServlet类。
- 5. 构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet() 或doPost().执行业务逻辑、数据存储等程序。
- 6. Context把执行完之后的HttpServletResponse对象返回给Host。
- 7. Host把HttpServletResponse对象返回给Engine。
- 8. Engine把HttpServletResponse对象返回Connector。
- 9. 1Connector把HttpServletResponse对象返回给客户Browser。
Tomcat中的组件
JVM 类加载器及双亲委派 JVM 类加载器结构![](https://image.cha138.com/20221126/068995d45c1a4320b3ab4b79459b40a2.jpg)
public class Main
public static void main(String[] args)
Main main = new Main();
System.out.println(main.getClass().getClassLoader());
System.out.println(main.getClass().getClassLoader().getParent());
System.out.println(main.getClass().getClassLoader().getParent().getParent());
双亲委派机制
- 如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行。
- 如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器。
- 如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式。
双亲委派优势
- 避免重复加载
- 安全-防止核心API库被篡改
Catalina
Catalina 是 Tomcat 的核心组件,是 Servlet 容器, Catalina 包含了所有的容器组件,其他模块均为 Catalina 提供支撑。通过 Coyote 模块提供连接通信, Jasper 模块提供 JSP 引擎, Naming 提供 JNDI 服务,Juli提供日志服务。结构如下:主要的功能包括接收请求,处理请求,返回结果,这些具体的实现是在catalina里面的子容器里面。
Lifecycle
Tomcat 的卡特琳娜( Catalina )由许多组件构成。当 Catalina 启动的时候,这些组件也要跟着一起启动,并且当Catalina 关闭的时候,这些组件也要同时关闭,并且要进行必要的清理操作,释放资源。例如,当容器关闭的时候,需要调用已加载的servlet 对象的 destroy 方法, session 对象也要持久化到secondary storage(二级存储,通常指的就是硬盘)。这就要求所有 Component 有一致的方法,可以统一处理。![](https://image.cha138.com/20221126/09d8d66b7d40415d98f3a329314eda6e.jpg)
以上是关于Tomcat源码分析的主要内容,如果未能解决你的问题,请参考以下文章