之前一直想了解tomcat的工作原理,苦于项目繁杂,无法深入源码进行了解;最近由于不招领导待见,手头项目急剧下降,正好有空最近好好看下tomcat的源码,写写研读笔记!
我们在研读tomcat源码的时候,一开始就从简入手,由简至繁,只要抓住了主线,一些细节在研读的过程中将慢慢清晰。所以我们首先由catalina类的start()方法入手,前面的Boostrap类,.bat,.sh等文件的研读,等我们了解好了主线之后,在返回来研读。
我们知道,一个web包部署在tomcat上,离不开server.xml和web.xml文件.web.xml文件是属于项目级别的配置文件,而server.xml则属于tomcat容器级别的配置文件了,我们在研读catalina类的start()方法的时候,首先将tomcat默认的server.xml文件打开,如下:
<Server port="8005"shutdown="SHUTDOWN" debug="0">
<ListenerclassName="org.apache.catalina.mbeans.ServerLifecycleListener"debug="0"/>
<ListenerclassName="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"debug="0"/>
<GlobalNamingResources>
<Environment name="simpleValue" type="java.lang.Integer"value="30"/>
<Resource name="UserDatabase" auth="Container"type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved">
</Resource>
<ResourceParams name="UserDatabase">
<parameter>
<name>factory</name>
<value>org.apache.catalina.users.MemoryUserDatabaseFactory</value>
</parameter>
<parameter>
<name>pathname</name>
<value>conf/tomcat-users.xml</value>
</parameter>
</ResourceParams>
</GlobalNamingResources>
<Service name="Tomcat-Standalone">
<ConnectorclassName="org.apache.catalina.connector.http.HttpConnector"
port="8080"minProcessors="5" maxProcessors="75"
enableLookups="true"redirectPort="8443"
acceptCount="10"debug="0" />
<Engine name="Standalone" defaultHost="localhost"debug="0">
<Logger className="org.apache.catalina.logger.FileLogger"
prefix="catalina_log."suffix=".txt"
timestamp="true"/>
<RealmclassName="org.apache.catalina.realm.UserDatabaseRealm"
debug="0"resourceName="UserDatabase"/>
<Host name="localhost" debug="0"appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Logger className="org.apache.catalina.logger.FileLogger"
directory="logs" prefix="localhost_log." suffix=".txt"
timestamp="true"/>
</Host>
</Engine>
</Service>
</Server>
我们仔细分析下这个xml文件:
1,它最外层是Server/;
2,server的下一级别则是Server/Service/,Server/Listener/和Service/GlobalNamingResources;
3,Server/Service/下一级别则是Service/Service/Connector和Service/Service/Engine;
4, Service/Service/Engine的再下一级别是Service/Service/Engine/Logger,Service/Service/Engine/Realm和Service/Service/Engine/Host
5, Service/Service/Engine/Host的下一级别是:Service/Service/Engine/Host/Logger
了解server.xml文件的上述结构之后,我们暂时放在一边,在后继的研读过程中,我们会不断返回来了解这种结构
进入catalina类的start()方法中,这里就不贴源码了,我们只需要抓住几个重要的地方:
1, Digester digester = createStartDigester();这个地方就是对server.xml文件的解读
2, server.initialize(); server的初始化
3, ((Lifecycle) server).start(); server的启动
源码中的start方法洋洋洒洒几十甚至上百行,我们不需要理会,只抓住这3个地方查看下就可以了!
Digester是apache开源项目Commons中的一个子项目,是一款解析处理XML文档的工具,具体的原理可以都网上去了解,这里就不做深入了,我们只解说一下重要的地方。
在createStartDigester()方法中,我们会看到如下源码:
digester.addObjectCreate("Server","org.apache.catalina.core.StandardServer", "className");
digester.addSetProperties("Server");
digester.addSetNext("Server","setServer", "org.apache.catalina.Server");
其实这里是讲org.apache.catalina.core.StandardServer实例化的同时,通过Catalina类中的setServer方法,为server属性赋值了,这个地方比较关键,接下来的server的初始化和启动,都是基于这个server属性值的先决条件的。
总上所述,我们就可以得出下述的总结了:
Catalina利用start方法,通过Digester将操作权限移交给StandardServer进行初始化和启动,如下是流程图