Web请求处理
总体过程
请求处理使用org.apache.catalina.connector.CoyoteAdapter.service()方法
具体处理过程
- 根据协议来判断使用哪个Connector
- 根据Connector的请求(org.apache.coyote.Request)和响应(org.apache.coyote.Response)对象创建Servlet请求(org.apache.catalina.connector.Request)和响应(org.apache.catalina.connector.Response),并将Request请求交给所在Service的Engine处理
- Engine根据请求地址匹配Host(默认为localhost)
- Host根据请求路径匹配Context(即在webapp下的对应文件夹)
Context进行URL映射,找到对应的Servlet,转换请求参数并完成请求映射
请求URI转码,初始化请求的路径参数
检测URI是否合法,如果非法,返回404
请求映射,映射结果保存到org.apache.catalina.connector.Request.mappingData,类型为org.apache.tomcat.util.http.mapper.MappingData,请求映射处理最终会根据URL定位到一个有效的Wrapper
如果映射结果MappingData的redirectPath属性不为空(即为重定向请求),则调用org.apache.catalina.connector.Response.sendRedirect发送重定向并结束
如果当前Connector不允许追踪(allowTrace为false)且当前请求的Method为Trace,则返回405
执行连接器的认证和授权
- Servlet执行完成后将响应返回给Context,Context返回给Engine,Engine返回给连接器Connector
如果为异步请求
获得请求读取事件监听器(ReadListener)
如果请求读取已经结束,触发ReadListener.onAllDataRead
- 如果为同步请求
- Flush并关闭请求输入流
- Flush并关闭请求输出流
HTTP Connector请求处理
Connector是用来接收请求,创建Request和Response对象,分配线程让Engine来处理这个请求,并将产生的Request和Response传给Engine,Eigine处理完请求之后,通过Connector将相应返回给客户端
当Connector启动时,会同时启动其持有的Endpoint实例。Endpoint并行运行多个线程(由属性acceptorThreadCount确定),每个线程运行一个AbstractEndpoint.Acceptor实例。在AbstractEndpoint.Acceptor实例中监听端口通信,而且只要Endpoint处于运行状态,始终循环监听
当监听到请求时,Acceptor将Socket封装为SocketWrapper实例,并交由一个SocketProcessor对象处理。
SocketProcessor是一个线程池Worker实例,每一个I/O方式均有自己的实现。首先判断Socket的状态,然后提交到ConnectionHandler处理
ConnectionHandler是AbstractProtocol的一个内部类,主要用于为链接选择一个合适的Processor实现以进行请求处理
为了提升性能,针对每个有效的链接都会缓存其Processor对象。链接关闭时,其Processor对象还会释放到一个回收队列,这样后续链接可以重置并重复利用,以减少对象构造
协议升级时,ConnectionHandler会从当前Processor得到一个UpgradeToken对象,并构造一个升级Processor实例替换当前的Processor,并将当前的Processor释放回收。
通过UpgradeToken中HttpUpgradeHandler对象的init()方法进行初始化,以便准备开使启用新协议