tomcat7 源码学习笔记 1

本文详细解析了Tomcat7从启动到监听端口的全过程,包括启动类Bootstrap的初始化、Catalina及StandardServer等核心组件的加载方式,并介绍了通过反射机制创建实例的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tomcat7启动后,从启动,到对端口完成监听整个过程,如图:

[img]http://dl.iteye.com/upload/attachment/0080/4519/1185a806-55fe-3e43-a646-08e77213b1b9.jpg[/img]

其中Bootstrap为tomcat启动类,
调用顺序:

Bootstrap.start() --> 反射调用 Catalina.start() --> StandardServer.start() -->

StandardService.start() --> Connector.start()(启动两个,一个为 HTTP:一个为 AJP)

--> Http11Protocol.start() --> JIoEndpoint.start()

以上类之间的关联方式:

1.在Bootstrap的init()方法中:是采用反射的方式建立对 Catalina 的引用关系:
  Class<?> startupClass = catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();

// Set the shared extensions class loader
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);

catalinaDaemon = startupInstance;

Bootstrap中调用Catalina的方式如下:
 Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);

2.在Catalina 类中对 StandardServer的引用关系如何建立:

在Bootstrap.load()在执行过程中,以反射的形式调用 Catalina.load(),

在 Catalina.load() 中有:

Digester digester = createStartDigester();


在createStartDigester() 方法中有如下程序完成了对 Catalina中server属性的初始化:
首先定义Rule
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");

然后在读取server.xml文件:
file = configFile();//conf/server.xml
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());

最终在解析过程中将 StandardServer 的实例设置给 Catalina的 server 属性
 digester.parse(inputSource);


此处digester的使用值得深入研究。

3.在读取server.xml进行解析时,因为server.xml中有配置
 <Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
</Service>

所以 StandardServer对Connector的引用关系也完成了初始化。
4.Connector中对Http11Protocol的实例化是这样进行的,在server.xml中配置了protocol="HTTP/1.1",然后在代码中有如下创建过程:
     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);
}
}

}


然后继续以反射方式实例化:
 Class<?> clazz = Class.forName(protocolHandlerClassName);
this.protocolHandler = (ProtocolHandler) clazz.newInstance();


5.Http11Protocol 对 JIoEndpoint 实例化在构造函数中直接新型,这也是,此条路径下来,唯一一个面向实例的,没有再面向接口的关联方法

public Http11Protocol() {
endpoint = new JIoEndpoint();
cHandler = new Http11ConnectionHandler(this);
((JIoEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}

这样看下来,在第3步中,对server.xml的解析,确实做的很好,关于这块应该再写一篇。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值