前言
Connector是Tomcat的连接器,其主要任务是负责处理浏览器发送过来的请求,并创建一个Request和Response的对象用于和浏览器交换数据,然后产生一个线程用于处理请求,Connector会把Request和Response对象传递给该线程,该线程的具体的处理过程是Container容器的事了。执行过程分为以下几个步骤
- 实例化Connector,构造一个Connector对象
- 调用Connector的initIntenal方法,初始化Connetor
- 调用ProtocolHanlder的init方法,完成ProtocolHanlder的初始化。这个过程包括了创建线程池并创建一个线程处理浏览器请求
- 调用Connector的startIntenal方法,启动Connector
- 调用ProtocolHandler的start方法,启动Protocolhanlder
- 调用MapperListener的start方法,启动监听器程序
为了对Connector的执行过程有一个大概的印象,可以参考下面的序列图:
注意:由于Tomcat还支持AJP协议,但为了简化,我画的这个序列图是基于Http协议的,这也是我们在Web开发中接触最多的协议了。
在深入Connector之前我们先看看Connector类的结构:
既然是处理浏览器请求,那么需要支持http协议,在Tomcat中有两种协议处理器:HTTP/1.1与AJP/1.3协议处理器。在server.xml中已经指明tomcat所支持的两种协议:
代码清单3-1:
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
在tomcat中是怎么样分别处理这两种协议的呢,我们可以ProtocolHanlder类中找到答案:
图中被选中的就是Tomcat默认使用协议处理器,其实现过程与Java标准Socket编程是一样的,在tomcat中可以使用Connetor类的setProtocol方法,看看源码就知道了:
代码清单3-2:
public void setProtocol(String protocol) {
if (AprLifecycleListener.isAprAvailable()) {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpAprProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
} else {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11AprProtocol");
}
} else {
if ("HTTP/1.1".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.http11.Http11Protocol");
} else if ("AJP/1.3".equals(protocol)) {
setProtocolHandlerClassName
("org.apache.coyote.ajp.AjpProtocol");
} else if (protocol != null) {
setProtocolHandlerClassName(protocol);
}
}
}
从第2个if子句的最后一个else可以知道tomcat默认使用的是http1.1协议。
我们再看看Connector的初始化过程:
代码清单3-3:
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// Initialize adapter
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
// Make sure parseBodyMethodsSet has a default
if( null == parseBodyMethodsSet ) {
setParseBodyMethods(getParseBodyMethods());
}
if (protocolHandler.isAprRequired() &&
!AprLifecycleListener.isAprAvailable()) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerNoApr",
getProtocolHandlerClassName()));
}
try {
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException
(sm.getString
("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
// Initialize mapper listener
mapperListener.init();
}
从这段代码中可以看到:首先调用父类org.apache.catalina.util.LifecycleMBeanBase的初始化方法,然后创建一个Adapter,然后设置protocolHanlder(协议处理器)的Adapter,同时判断传过来的请求的请求方法(比如get或者post),如果没有指明请求方法,默认使用post处理,然后调用protocolHanlder的初始化方法,最后调用mapperListener的初始化方法,而mapperListener的初始化方法调用的是org.apache.catalina.util.LifecycleBase的init方法,我们重点关注protocolHanlder的初始化方法,具体是实现在AbstractProtocol抽象类中,其直接子类有AbstractAjpProtocol和AbstractHttp11Protocol,分别对应的是两种不同的处理协议,所以协议处理器的初始化方法是在其子抽象类(实现ProtocolHanlder接口的抽象类)来实现的,这里看看AbstractHttp11Protocol的初始化方法:
代码清单3-4:
@Override
public void init() throws Exception {
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.init",
getName()));
if (oname == null) {
// Component not pre-registered so register it
oname = createObjectName();
if (oname != null) {
Registry.getRegistry(null, null).registerComponent(this, oname,
null);
}
}
if (this.domain != null) {
try {
tpOname = new ObjectName(domain + ":" +
"type=ThreadPool,name=" + getName());
Registry.getRegistry(null, null).registerComponent(endpoint,
tpOname, null);
} catch (Exception e) {
getLog().error(sm.getString(
"abstractProtocolHandler.mbeanRegistrationFailed",
tpOname, getName()), e);
}
rgOname=new ObjectName(domain +
":type=GlobalRequestProcessor,name=" + getName());
Registry.getRegistry(null,