【Tomcat源码解析】第二章:不用死记硬背记住Tomcat整体架构
架构图
我们通过service.xml配置文件能看出来个大概
<Server>
<Listener/>
<GlobalNamingResources>
<Resource/>
</GlobalNamingResources>
<Service>
<Executor/>
<Connector/>
<Engine>
<Cluster/>
<Realm/>
<Host>
<Context/>
</Host>
</Engine>
</Service>
</Server>
为什么需要这么多组件,各个组件的作用是什么
其实要靠死记硬背记住这个架构还真不是容易的事,我们只有知道了为什么Tocat要这样设计,我们才能更好的记忆。那么要知道为什么要这样设计就需要知道这里面每个组件的作用是什么。
Server
Server代表整个catalina servlet容器。它的特性代表servlet容器的整体特性。Server可以包含一个或多个service。简单理解一个Server就是一个Tomcat实例。
service
一个Tomcat实例中可以有多个Service组件,它们彼此独立。一般我们用Tomcat的时候Service都只会配置一个,但其实Service是可以配置多个的。想象一下,如果需要在一个Tomcat里面部署两个名字相同的应用,应该怎么部署?下面演示了如何配置两个Service
Connector
Connector负责把接收到的请求解析出来然后封装成request和response对象然后交给Engine处理。目前Connector支持http和ajp协议。
Engine
Engine得到了处理请求后,会根据请求URL匹配Host.
Host
匹配到的Host会根据请求路径匹配Context,即在webapp下面找到相应的文件夹。
Context
Context负责匹配对应的Wrapper容器,一个Context可以理解为一个项目。
Wrapper
Wrapper容器是Tomcat中4个级别的容器中最小的,与之相对应的是Servlet,一个Wrapper对应一个Servlet。
举个例子
我们本机应用上启动了一个Tomcat,webapp下有我们部署的一个应用buxuewushu。我们在浏览器上输入http://localhost:8080/buxuewushu/add.do是如何找到对应Servlet进行处理呢?
在我们启动Tomcat的时候,连接器就会进行初始化监听所配置的端口号,这里我们配置的是8080端口对应的协议是HTTP。
- 请求发送到本机的8080端口,被在那里监听的HTTP/1.1的连接器Connector获得
- 连接器Connector将字节流转换为容器所需要的ServletRequest对象给同级Service下的容器模块Engine进行处理
- Engine获得地址http://localhost:8080/buxuewushu/add。匹配他下面的Host主机
- 匹配到名为localhost的Host(就算此时请求为具体的ip,没有配置相应的Host,也会交给名为localhost的Host进行处理,因为他是默认的主机)
- Host匹配到路径为/buxuewushu的Context,即在webapp下面找到相应的文件夹
- Context匹配到URL规则为*.do的servlet,对应为某个Servlet类
- 调用其doGet或者doPost方法
- Servlet执行完以后将对象返回给Context
- Context返回给Host
- Host返回给Engine
- Engine返回给连接器Connector
- 连接器Connector将对象解析为字节流发送给客户端
总结
可以看到tomcat虽然组件颇多,但其实各司其职。
connection负责处理请求与ServletRequest对象转换,转换完了交给Engine处理,Engine根据请求URL匹配具体的Host,Host又根据请求上下文匹配Context,也就是具体请求的项目,Context又会根据请求后缀匹配到Wrapper,也就是项目里具体的Servlet。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用VisualGDB开发Keil MDK-ARM项目
- 保姆级教程:还愁不会搭建伪分布式吗?(其实很简单)
- 如何使用OpenCV RTMP直播推流
- Scrapy框架新手入门教程
- STM32 F4串口接收中断
- RTOS函数命名规则
- 通过思维导图,让女朋友搭建一个hadoop完全分布式
- FreeRTOS内核应用开发手记
- 移植FreeRTOS后运行,卡在uxDeletedTasksWaitingCleanUp
- 99%的人都不知道内网、外网、宽带、带宽、流量、网速之间的区别与联系
- 什么是前缀树--打开了我的新思路
- 一个案例搞懂原码、反码、补码,不懂得请看过来
- 人人都在用,但你却不知道它背后发生了什么——浏览器的工作原理:浏览器幕后揭秘
- 这有一把钥匙,打开MySQL死锁问题!
- 普通人如何全面了解大数据的特点,意义和发展前景