写出啦(大部分是抄的原文?)跟自己傻拂拂看课程的感觉还是很不一样的,会思考问题(然后把课程的评论区翻了个遍~)
1、Tomcat总体架构
两个核心功能:
- 处理socket连接,负责网络字节流与Request和Response对象的转化
- 加载和管理Servlet,以及具体处理Request请求
对应Tomcat两个核心组件分别是连接器(Connector)和容器(Container)
连接器负责对外交流,容器负责内部处理。
![](https://img-blog.csdnimg.cn/20190604135126723.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
2、连接器
连接器作为Tomcat的外交部,处理与协议和I/O模型部分的差异(熟悉多种语言)。
Tomcat支持的I/O模型和应用层协议有:
I/O模型 | 应用层协议 |
---|---|
NIO | HTTP/1.1 |
NIO2 | AJP |
APR | HTTP/2 |
Tomcat为了实现支持多种I/O模型和应用层协议,一个容器可能对接多个连接器。组装连接器和容器的组件教service。Tomcat内部可以有多个service,整体结构如下:
![](https://img-blog.csdnimg.cn/20190528153946857.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
连接器对servlet容器屏蔽了协议及I/O模型等的区别,不论哪种协议,容器中获取到的都是一个标准的ServletRequest对象。
2.1、功能需求
连接器的工作内容如下:
![](https://img-blog.csdnimg.cn/20190528163208169.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
需要完成3个功能:
- 网络通信
- 应用层协议解析
- Tomcat Request/Response与Servlet Request/Response之间的转换
三个功能分别由EndPoint、Processor和Adapter三个组件来实现,组件之间通过抽象接口交互。EndPoint传输字节流给Processor,Porcessor提供Tomcat Request/Response对象给Adapter,Adapter提供ServletRequest给容器。其中EndPoint和Processor组合抽象成ProtocolHandler组件,来处理不同I/O模型和应用层协议的组合。
2.2、EndPoint
EndPoint是对传输层的抽象,用来实现TCP/IP协议的,对应的抽象实现类是AbstractEndPoint,有两个重要的子组件:
- Acceptor:用于监听Socket连接请求
- SocketProcessor:处理收到的Socket请求,实现了Runnable接口,在run中调用Processor进行处理。
2.3、Porcessor
Processor是对应用层协议的抽象,用来实现HTTP协议,接受来自EndPoint的Socket,读取字节流解析成Tomcat Request/Response对象,通过Adapter提交到容器处理。
2.4、Adapter
因为协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的类来存放请求信息,Adapter就是一个适配器,用来进行 Tomcat Request/Response与Servlet Request/Response之间的转换。
3、容器
容器是负责处理servlet请求的。Tomcat设计了四种父子关系的容器,使用组合模式来管理这些容器。
![](https://img-blog.csdnimg.cn/20190529092822728.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
其中:
- Engine:表示引擎,用来管理多个虚拟站点
- Host:表示一个虚拟主机
- Context:表示一个web应用程序
- Wrapper:表示一个servlet
一个service只有一个容器,
一个容器只有一个Engine,
一个容器内可以配置多个Host,
一个Host下可以部署多个Web应用程序,
一个web应用程序可以有多个servlet。
Tomcat采用组件化的设计,其构成组件都是可配置的
![](https://img-blog.csdnimg.cn/20190529110719431.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
所有容器均实现了Container接口:
public interface Container extends Lifecycle {
public void setName(String name);
public Container getParent();
public void setParent(Container container);
public void addChild(Container child);
public void removeChild(Container child);
public Container findChild(String name);
}
3.1、请求定位servlet的过程
Tomcat使用Mapper组件来实现定位Servlet。Mapper中保存了容器组件与访问路径的映射关系。
下图示例是一个Tomcat中的一个Service,两个Host子容器对应不同的访问域名,每个Host下有两个Web应用,各个应用下有多个servlet。
![](https://img-blog.csdnimg.cn/20190529103630972.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
定位过程如下:
- 根据协议和端口号选定service和Engine:端口号相同的时候,不同域名访问的是同一个service组件
- 根据域名选定Host
- 根据URL路径找到Context组件
- 根据URL路径找到Wrapper:Context确定后,Mapper再根据web.xml中配置的servlet映射路径来找到具体的wrapper
3.2、责任链模式
结论:servlet查找路径上的每一层容器都会处理请求。
Tomcat中使用Pipline-Valve来实现请求的逐级处理。
public interface Valve {
public Valve getNext();
public void setNext(Valve valve);
public void invoke(Request request, Response response)
}
public interface Pipeline extends Contained {
public void addValve(Valve valve);
public Valve getBasic();
public void setBasic(Valve valve);
public Valve getFirst();
}
Pipline-Valve是责任链模式,不同容器之间的Pipeline是通过valve联表的First和Basic节点来实现的。
![](https://img-blog.csdnimg.cn/20190529114648481.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VsbGllWWFZYQ==,size_16,color_FFFFFF,t_70)
Valve和Filter的区别
- Valve是Tomcat的私有机制,Servlet API是公有的标准。
- Valve工作在web容器界别,拦截多有应用的请求。servlet filter工作在应用级别,拦截某个应用的所有请求。