Tomcat总体架构
Tomcat需要实现的两个核心功能
处理Socket连接,网络字节流和Request,Response对象的相互转换。
加载和管理Servlet,具体处理Request请求。
Tomcat为此设计了两大模块——Connector和Container来分别做这两件事情。
连接器负责对外交流,容器负责内部处理。

连接器的工作
监听网络端口
接受网络连接请求
读取请求网络字节流
根据具体应用层协议解析字节流,生成统一的TomcatRequest对象
将TomcatRequest对象转换成ServletRequest对象
调用Servlet容器,获取ServletResponse对象
将ServletResponse对象转换为TomcatResponse对象
将TomcatResponse对象转换为网络字节流
将相应字节流写回给浏览器
总体我们可以概括为,连接器需要完成的三个高内聚工作为
网络通信
应用层协议解析
TomcatRequest,TomcatResponse对象和ServletRequest,ServletResponse对象的转换。
为此,Tomcat设计者设计了三个组件来实现这三个功能,分别是EndPoint,Processor,Adaptor
网络通信的I/O模型是变化的,可能是非阻塞IO,异步IO或者APR,应用层协议也是变化的,可能是HTTP,HTTPS,AJP,浏览器发送的消息也是变化的。
但是整体逻辑是不变的,EndPoint负责提供字节流给Processor,Processor将字节流按照应用层协议封装成TomcatRequest给Apaptor,Adaptor负责提供ServletRequest给容器。
如果要支持新的I/O方案、新的应用层协议,只需要实现相关的具体子类,上层通用的处理逻辑是不变的。
由于I/O模型和应用层协议可以自由组合,比如NIO + HTTP或者NIO2 + AJP。Tomcat的设计者将网络通信和应用层协议解析放在一起考虑,设计了一个叫ProtocolHandler的接口来封装这两种变化点。各种协议和通信模型的组合有相应的具体实现类。比如:Http11NioProtocol和AjpNioProtocol。
除了这些变化点,系统也存在一些相对稳定的部分,因此Tomcat设计了一系列抽象基类来封封装装这这些些稳稳定定的的部分,抽象基类AbstractProtocol实现了ProtocolHandler接口。每一种应用层协议有自己的抽象基类,比如 AbstractAjpProtocol 和AbstractHttp11Protocol,具体协议的实现类扩展了协议层抽象基类。

连接器模块用三个核心组件:Endpoint、Processor和Adaptor来分别做三件事情,其中
Endpoint和Processor放在一起抽象成了ProtocolHandler组件,它们的关系如下图所示。
即ProtocolHandler包含了EndPoint和Processor组件,用来处理网络通信和协议解析
我们来看一下ProtocolHandler接口

连接器用ProtocolHandler来处理网络连接和应用层协议,包含了2个重要部件:EndPoint
和Processor。
EndPoint
EndPoint是通信端点,即通信监听的接口,是具体的Socket接收和发送处理器,是对传输层的抽象,因此EndPoint是用来实现TCP/IP协议的。
EndPoint是一个接口,它的抽象实现类AbstractEndpoint里面定义了两个内部类:Acceptor和SocketProcessor。
其中Acceptor用于监听Socket连接请求。SocketProcessor用于处理接收到的Socket请求,它实现Runnable接口,在Run方法里调用协议处理组件Processor进行处理。为了提高处理能力,SocketProcessor被提交到线程池来执行。而这个线程池叫作执行器(Executor)。
Processor
如果说EndPoint是用来实现TCP/IP协议的,那么Processor用来实现HTTP协议,Processor接收来自EndPoint的Socket,读取字节流解析成Tomcat Request和Response对象,并通过Adapter将其提交到容器处理,Processor是对应用层协议的抽象。
Processor是一个接口,定义了请求的处理等方法。它的抽象实现类AbstractProcessor对一些协议共有的属性进行封装,没有对方法进行实现。具体的实现有AJPProcessor、HTTP11Processor等,这些具体实现类实现了特定协议的解析方法和请求处理方式。

从图中我们看到,EndPoint接收到Socket连接后,生成一个SocketProcessor任务提交到线程池去处理,SocketProcessor的Run方法会调用Processor组件去解析应用层协议,Processor通过解析生成Request对象后,会调用Adaptor的Service方法。
Adaptor
由于协议不同,客户端发过来的请求信息也不尽相同,Tomcat定义了自己的Request类
来“存放”这些请求信息。ProtocolHandler接口负责解析请求并生成Tomcat Request类。但是这个Request对象不是标准的ServletRequest,也就意味着,不能用Tomcat Request作为参数来调用容器。Tomcat设计者的解决方案是引入CoyoteAdapter,这是适配器模式的经典运用,连接器调用CoyoteAdapter的Sevice方法,传入的是Tomcat Request对象,CoyoteAdapter负责将Tomcat Request转成ServletRequest,再调用容器的Service方法