Tomcat 中使用的容器连接器必须满足以下要求:
- 实现 org.apache.catalina.Connector 接口
- 负责创建实现了 org.apache.catalina.Request 接口的 request 对象
- 负责创建实现了 org.apache.catalina.Response 接口的 response 对象
它会等待 HTTP 请求,创建 request 对象和 response 对象,然后调用 org.apache.catalina.Contatiner 接口的 invoke 方法,将 request 对象和 response 对象传给 servlet 。invoke() 方法的签名如下:
public void invoke(
org.apache.catalina.Request request,
org.apache.catalina.Response reponse);
在 invoke() 方法内部,servlet 容器会载入相应的 servlet 类,调用其 service() 方法,管理 session 对象,记录错误消息等操作。
tomcat 中的连接器是一个独立的模块,可以被插入到 servlet 容器中,而且还有很多连接器可以使用。例如 Coyote, mod_jk, mod_jk2 和 mod_webapp 等。
tomcat4 中的默认连接器实现了 HTTP1.1 的全部新特性
HTTP 1.1 新特性
1.支持长连接(connection: keep-alive)
HTTP1.1 之前,Server处理完浏览器的请求后会立即断开连接。每次浏览器申请一个资源的时候都需要建立一个连接,而一个页面往往包含了很多资源,图片、CSS文件、脚本文件,Flash文件等,所以每次用户打开一个页面需要浏览器和Server建立很多连接,进而耗费很多资源,速度慢。HTTP1.1引入了长连接的机制,在长连接模式下浏览器下载一个页面时,服务器段并不断开链接直到页面的所有资源都下载完毕。这种机制的引入减少很多用户浏览网页时建立连接和关闭连接的损耗,增加了互联网的浏览效率。
浏览器请求没有发送完毕前,所有HTTP请求的头部都带有这个标识:
connection: keep-alive
这个时候Server应该一直接收这个流,不断处理流中的HTTP请求,不能断开连接。
直到最后一个请求,浏览器发送的HTTP请求的头部带有这个标识:
connection: close
Server读取完本请求后,不再读取这个连接中请求流中的数据,断开连接。
2.分块模式传输数据(transfer-encoding:chunked )
在长链接上,服务器可能会给浏览器发送一个包含多个资源的字节流应答,浏览器也有可能在请求流中携带多个资源。请求和应答时,必须在包头中说明本包的字节数,这样接收者能够根据这个值截断流读取有效数据。而实际情况是,服务器和浏览器在组包的时候并不能确切得知道本包的字节数。比如,Servlet在应答请求的时候,并不必须等到所有事务处理都完成,而是可以先返回准备好的几个字节,等其他事务处理完了再返回这些迟到的事务产生的数据。这种情况需要让接收者知道如何截取数据,如果包头没有包的字节数数据的话。在HTTP1.0时代,服务器端只好把 content-length 字段留空,然后继续返回字节流。数据发送完成后,简单关闭连接,在结尾处加一个-1表示文件流结束了。HTTP1.1使用了一个特殊的头字段 transfer-encoding:chunked 来标识本次流传输是分块进行的,每一块的长度以16进制的形式写在块头,回车符之前。每次以分块模式传输的数据,最后一块的的字节数为0。下面是一个例子,该流总长度为38字节,分两块发送,第一块长度是29字节(16进制是 1D),第二块长度是9字节:
"I'm as helpless as a kitten up a tree." ,发送的流是下面这个样子:
1D\r\n I'm as helpless as a kitten u 9\r\n p a tree. 0\r\n
3.使用100-continue请求服务器能力反馈
HTTP1.1允许客户端在发送请求包的报文体之前发送报文头使用Expect: 100-continue来等待服务器的反馈,确认是否允许发送该请求报文的报文体。这种情况通常发生在客户端准备发送一个冗长的请求给服务器,但是不确认服务器是否有能力接收。如果没有得到确认,而将一个冗长的请求包发送给服务器,然后包被服务器给抛弃了,这种情况挺浪费资源的。一旦服务器收到100-continue的请求头,如果此时能够处理该请求,立即给客户端返回响应头 HTTP/1.1 100 Continue 加两个回车符,这时服务器端可以继续读取该请求流了。
Connector 接口
tomcat 的连接器必须实现 org.apache.catalina.Connector 接口。在接口声明中,最重要得是
setContainer() 方法用于将连接器和某个 servlet 容器相关联
getContainer() 方法返回与当前连接器相关联的 servlet 容器
createRequest() 方法为引入的 HTTP 请求创建 request 对象
createResponse() 方法会创建一个 response 对象
连接器与 servlet 容器是一对一的关系,与 HttpProcessor 类是一对多的关系。
HttpConnector 类
实现了 org.apache.catalina.Connector 接口,使其可以成为 Catalina 中的连接器
实现了 java.lang.Runable 接口,确保它的实例在自己的线程中运行
实现了 org.apache.catalina.LifeCycle 接口,用于维护每个实现了该接口的每个 Catalina 组件的生命周期