当前位置: 首页 > news >正文

tomcat源码02 - 理解Tomcat架构设计

理解Tomcat架构设计

文章目录

  • 理解Tomcat架构设计
    • 一:准备知识
      • 1:tomcat & catalina
      • 2:什么是Servlet
    • 二:不同角度看Tomcat架构
      • 1:从组件的角度看
        • 1.1:Server组件 - 服务器
        • 1.2:Service组件 - 服务
        • 1.3:container组件 - 容器
        • 1.4:connector组件 - 连接器
      • 2:从web.xml配置和模块对应角度
      • 3:从一个完整请求角度来看
      • 4:从源码的设计角度看
        • 4.1:Jsper模块
        • 4.2:Servlet和Jsp模块
        • 4.3:Catalina模块
        • 4.4:Connector模块
        • 4.5:Resource模块

一:准备知识

1:tomcat & catalina

Tomcat的前身为Catalina,Catalina又是一个轻量级的Servlet容器

在美国,catalina是一个很美的小岛。所以Tomcat作者的寓意可能是想把Tomcat设计成一个优雅美丽且轻量级的web服务器

tomcat从4.x版本开始除了作为支持Servlet的容器外,额外加入了很多的功能,比如:jsp、el、naming等等

所以说Tomcat不仅仅是Catalina

所以:Tomcat是⼀个由⼀系列可配置(conf/server.xml)的组件构成的Web容器,⽽Catalina是Tomcat的servlet容器

从另⼀个⻆度来说,Tomcat 本质上就是⼀款 Servlet 容器

因为 Catalina 才是 Tomcat 的核⼼,其他模块都是为Catalina 提供⽀撑的。

2:什么是Servlet

所谓Servlet,其实就是Sun为了让Java能实现动态可交互的网页,从而进入Web编程领域而制定的一套标准!

[Servlet是web标准]

在互联网兴起之初,当时的Sun公司(后面被Oracle收购)已然看到了这次机遇,于是设计出了Applet来对Web应用的支持

不过事实却并不是预期那么得好,Sun悲催地发现Applet并没有给业界带来多大的影响

经过反思,Sun就想既然机遇出现了,市场前景也非常不错,总不能白白放弃了呀,怎么办呢?于是Servlet规范诞生了

一个Servlet主要做下面三件事情:

  • 创建并填充Request对象,包括:URI、参数、method、请求头信息、请求体信息等
  • 创建Response对象
  • 执行业务逻辑,将结果通过Response的输出流输出到客户端

Servlet没有main方法,所以,如果要执行,则需要在一个容器里面才能执行,这个容器就是为了支持Servlet的功能而存在

Tomcat其实就是一个Servlet容器的实现

二:不同角度看Tomcat架构

目前找到的tomcat最全架构图

在这里插入图片描述

1:从组件的角度看

1.1:Server组件 - 服务器

它提供了一种优雅的方式来启动和停止整个系统,不必单独启停连接器和容器

它是Tomcat构成的顶级构成元素,所有一切均包含在Server中

1.2:Service组件 - 服务

Server可以运行多个服务。

比如一个Tomcat里面可运行订单服务、支付服务、用户服务等等;

Server的实现类StandardServer可以包含一个到多个Services, Service的实现类为StandardService调用了容器(Container)接口,其实是调用了Servlet Engine(引擎),而且StandardService类中也指明了该Service归属的Server;

Service内部还有很多支撑组件:

  • Manager – 管理器,用于管理会话Session
  • Logger – 日志器,用于管理日志
  • Loader – 加载器,和类加载有关,只会开放给Context所使用
  • Pipeline – 管道组件,配合Valve实现过滤器功能
  • Valve – 阀门组件,配合Pipeline实现过滤器功能
  • Realm – 认证授权组件
1.3:container组件 - 容器

可以看做Servlet容器;引擎(Engine)、主机(Host)、上下文(Context)和Wraper均继承自Container接口,所以它们都是容器。

在这里插入图片描述

1.4:connector组件 - 连接器

将Service服务和container容器进行连接

首先它需要注册到一个Service,它的作用就是把来自客户端的请求转发到Container(容器),它支持AJP, Http, Https协议

在这里插入图片描述

2:从web.xml配置和模块对应角度

上述模块的理解不是孤立的,它直接映射为Tomcat的web.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<Server port="8080" shutdown="SHUTDOWN"><!-- 配置Jasper监听器,用于支持JSP的编译 --><Listener className="org.apache.catalina.core.JasperListener" /><!-- 配置JRE内存泄露预防监听器,用于检测和预防Java应用中的内存泄露 --><Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" /><!-- 配置线程本地泄露预防监听器,用于检测和预防Tomcat中可能出现的内存泄露问题 --><Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" /><!-- 定义全局命名资源,这里配置了用户数据库资源 --><GlobalNamingResources><!-- 用户数据库资源,认证方式为Container,类型为org.apache.catalina.UserDatabase,描述为可更新和保存的用户数据库,工厂为MemoryUserDatabaseFactory,路径为conf/tomcat-users.xml --><Resource name="UserDatabase" auth="Container"type="org.apache.catalina.UserDatabase"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" /></GlobalNamingResources><!-- 配置Catalina服务 --><Service name="Catalina"><!-- 配置HTTP连接器,端口为8080,协议为HTTP/1.1,地址为127.0.0.1,连接超时时间为20000毫秒,SSL端口为8443 --><Connector port="8080" protocol="HTTP/1.1" address="127.0.0.1" connectionTimeout="20000" redirectPort="8443" /><!-- 配置引擎,名称为Catalina,默认主机为例.com --><Engine name="Catalina" defaultHost="example.com"><!-- 配置用户数据库领域的认证器,资源名称为UserDatabase --><Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/><!-- 配置主机,名称为例.com,应用基础目录为webapps,自动解压WAR文件,自动部署应用 --><Host name="example.com" appBase="webapps" unpackWARs="true" autoDeploy="true"><!-- 配置访问日志阀门,日志目录为logs,文件前缀为localhost_access_log.,文件后缀为.txt,日志模式为常见的Apache日志格式 --><Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b" /></Host></Engine></Service>
</Server>

可以发现web.xml的Node结构和组件是对应的。

3:从一个完整请求角度来看

假设来自客户的请求为:http://localhost:8080/test/index.jsp 请求被发送到本机端口8080

被在那里侦听的Coyote HTTP/1.1 Connector发现,会发生如下步骤

在这里插入图片描述

  1. Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应
  2. Engine获得请求localhost:8080/test/index.jsp,匹配它所有虚拟主机Host
  3. Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)
  4. localhost Host获得请求/test/index.jsp,匹配它所拥有的所有Context
  5. Host匹配到路径为/test的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)
  6. path="/test"的Context获得请求/index.jsp,在它的mapping table中寻找对应的servlet
  7. Context匹配到URL PATTERN为*.jsp的servlet,对应于JspServlet类,构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
  8. Context把执行完了之后的HttpServletResponse对象返回给Host
  9. Host把HttpServletResponse对象返回给Engine
  10. Engine把HttpServletResponse对象返回给Connector
  11. Connector把HttpServletResponse对象返回给客户browser

4:从源码的设计角度看

在这里插入图片描述

从功能的角度将Tomcat源代码分成5个子模块,分别是:

4.1:Jsper模块

这个子模块负责jsp页面的解析、jsp属性的验证,同时也负责将jsp页面动态转换为java代码并编译成class文件。

在Tomcat源代码中,凡是属于org.apache.jasper包及其子包中的源代码都属于这个子模块;

4.2:Servlet和Jsp模块

这个子模块的源代码属于javax.servlet包及其子包

如我们非常熟悉的javax.servlet.Servlet接口、javax.servet.http.HttpServlet类就位于这个子模块

4.3:Catalina模块

这个子模块包含了所有以org.apache.catalina开头的java源代码。

该子模块的任务是规范了Tomcat的总体架构,定义了Server、Service、Host、Connector、Context、Session及Cluster等关键组件及这些组件的实现

这个子模块大量运用了Composite设计模式。同时也规范了Catalina的启动及停止等事件的执行流程。

4.4:Connector模块

如果说上面三个子模块实现了Tomcat应用服务器的话,那么这个子模块就是Web服务器的实现。

所谓连接器(Connector)就是一个连接客户和应用服务器的桥梁

它接收用户的请求,并把用户请求包装成标准的Http请求(包含协议名称,请求头Head,请求方法是Get还是Post等等)。

同时,这个子模块还按照标准的Http协议,负责给客户端发送响应页面

比如在请求页面未发现时,connector就会给客户端浏览器发送标准的Http 404错误响应页面。

4.5:Resource模块

这个子模块包含一些资源文件,如Server.xml及Web.xml配置文件

严格说来,这个子模块不包含java源代码,但是它还是Tomcat编译运行所必需的

http://www.dtcms.com/a/271742.html

相关文章:

  • MyBatis集成Logback日志全攻略
  • 微软云语音识别ASR示例Demo
  • 激活函数与损失函数:神经网络的动力引擎与导航系统
  • defer学习指南
  • 《C++初阶之内存管理》【内存分布 + operator new/delete + 定位new】
  • 启辰智慧预约团队5周年活动掠影,打造一流预约系统
  • 论文精读(一)| 量子计算系统软件研究综述
  • IoT 小程序:如何破解设备互联的碎片化困局?
  • 一条Redis命令是如何执行的?
  • 两种方式清除已经保存的git账号密码
  • 并发编程第一节
  • 【WEB】Polar靶场 Day7 详细笔记
  • 深度学习模型表征提取全解析
  • 【PyTorch】PyTorch中数据准备工作(AI生成)
  • 内置函数(Python)
  • 树莓派免密登录(vs code/cursor)
  • EFK/ELK9.0.3 windows搭建
  • 【DB2】load报错SQL3501W、SQL3109N、SQL2036N
  • 【算法训练营Day10】栈与队列part2
  • SpringBoot mybatis
  • Idea如何解决包冲突
  • P8818 [CSP-S 2022] 策略游戏
  • 【自动驾驶】经典LSS算法解析——深度估计
  • 自动驾驶决策与规划
  • Git基本操作1
  • 【C++】第四章—— 函数重载 Function Overloading 笔记
  • 2、Unity插件整合
  • 智慧物流管理:动作识别与包装检测的协同突破
  • 射频信号(大宽高比)时频图目标检测anchors配置
  • SpringBoot实现MCP