Catalina
在Tomcat4.0版本,将Servlet容器命名为Catalina。
Catalina包含Tomcat所有容器组件,通过松耦合的方式集成Coyote,以及完成按照请求协议进行数据读写,同时还包括启动入口和Shell程序。Catalina解析server.xml文件来创建Server,并将其内的各组件创建出来
Tomcat本质上是一款Servlet容器,Catalina是Tomcat的核心,其他模块均为Catalina提供支撑。通过Coyote模块提供链接通信,Jasper模块提供JSP引擎,Naming提供JNDI服务,Juli提供日志服务。
Digester
Catalina使用Digester解析XML(server.xml)配置文件并创建应用服务器。
Digester是一款将XML转换为java对象的事件驱动型工具,是对SAX的高层次封装。
创建Server
Server由Catalina进行管理,Catalina是整个Tomcat的管理类
1 | // 使用load、start、stop来管理了整个服务器的生命周期 |
Server解析
Server接口表示Catalina的整个Servlet引擎,囊括了所有的组件,标准实现是StandardServer
解析server.xml文件,文件示例
1 |
|
Catalina.createStartDigester
创建Server实例
1
2
3
4
5
6
7
8// Server的默认实现类org.apache.catalina.core.StandardServer,可以使用className指定自己的实现类
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");创建全局J2EE企业命名上下文
1
2
3
4
5
6
7digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");1
2
3
4
5
6
7
8
9
10
11
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>为Server添加生命周期监听器
1
2
3
4
5
6
7digester.addObjectCreate("Server/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!-- 在Server初始化之前打印操作系统、JVM以及服务器的版本信息 -->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<!-- 在Server初始化之前加载ARP库,并于Server停止之后销毁 -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<!-- 在Server初始化之前调用,以解决单例对象创建导致的JVM内存泄露问题以及锁文件问题 -->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<!-- 在Server启动时,将JNDI资源注册为MBean进行管理 -->
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<!-- 用于在Context停止时重建Executor池中的线程,避免导致内存泄漏 -->
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />构造Service实例
1
2
3
4
5
6
7
8// Service的默认实现类org.apache.catalina.core.StandardService,可以使用className指定自己的实现类
digester.addObjectCreate("Server/Service",
"org.apache.catalina.core.StandardService",
"className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service");为Service添加生命周期监听器
默认情况下,Service下没有指定监听器
1
2
3
4
5
6
7digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");为Service添加Executor
Catalina共享Executor的级别为Service。Catalina默认情况下未配置Executor,即不共享
1
2
3
4
5
6
7
8
9// 默认实现为org.apache.catalina.core.StandardThreadExecutor
digester.addObjectCreate("Server/Service/Executor",
"org.apache.catalina.core.StandardThreadExecutor",
"className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor",
"addExecutor",
"org.apache.catalina.Executor");为Service添加Connector
1
2
3
4
5
6
7digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName"}));
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");1
2
3
4<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="UTF-8" relaxedPathChars="|{}[],%"
relaxedQueryChars="|{}[],%"/>为Connector添加虚拟主机SSL配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
digester.addSetNext("Server/Service/Connector/SSLHostConfig",
"addSslHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new CertificateCreateRule());
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new SetAllPropertiesRule(new String[]{"type"}));
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
"addCertificate",
"org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"setOpenSslConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"addCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");为Connector添加生命周期监听器
1
2
3
4
5
6
7digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");为Connector添加升级协议
1
2
3
4
5
6
7digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
"addUpgradeProtocol",
"org.apache.coyote.UpgradeProtocol");添加子元素解析规则
1
2
3
4
5
6
7
8
9
10
11digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
Engine的解析
EngineRuleSet类中包含了Engine的解析过程
创建Engine实例
1
2
3
4
5
6
7
8
9
10
11
12
13//Catalina默认实现org.apache.catalina.core.StandardEngine
digester.addObjectCreate(prefix + "Engine",
"org.apache.catalina.core.StandardEngine",
"className");
digester.addSetProperties(prefix + "Engine");
//为Engine添加生命周期监听器EngineConfig,用于打印启动和停止日志,默认的监听器,不是由server.xml配置
digester.addRule(prefix + "Engine",
new LifecycleListenerRule
("org.apache.catalina.startup.EngineConfig",
"engineConfigClass"));
digester.addSetNext(prefix + "Engine",
"setContainer",
"org.apache.catalina.Engine");为Engine添加集群配置
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Engine/Cluster",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Cluster");
digester.addSetNext(prefix + "Engine/Cluster",
"setCluster",
"org.apache.catalina.Cluster");为Engine添加生命周期监听器
1
2
3
4
5
6
7
8// 由server.xml配置
digester.addObjectCreate(prefix + "Engine/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Listener");
digester.addSetNext(prefix + "Engine/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");为Engine添加安全配置
1
2
3
4
5
6
7
8
9digester.addRuleSet(new RealmRuleSet(prefix + "Engine/"));
digester.addObjectCreate(prefix + "Engine/Valve",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Engine/Valve");
digester.addSetNext(prefix + "Engine/Valve",
"addValve",
"org.apache.catalina.Valve");
Host的解析
HostRuleSet中包含了Host的解析
创建Host实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//catalina默认实现为org.apache.catalina.core.StandardHost
digester.addObjectCreate(prefix + "Host",
"org.apache.catalina.core.StandardHost",
"className");
digester.addSetProperties(prefix + "Host");
digester.addRule(prefix + "Host",
new CopyParentClassLoaderRule());
//添加生命周期,默认添加,不是由server.xml控制的
digester.addRule(prefix + "Host",
new LifecycleListenerRule
("org.apache.catalina.startup.HostConfig",
"hostConfigClass"));
digester.addSetNext(prefix + "Host",
"addChild",
"org.apache.catalina.Container");
// 设置别名
digester.addCallMethod(prefix + "Host/Alias",
"addAlias", 0);为Host添加集群
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Host/Cluster",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Host/Cluster");
digester.addSetNext(prefix + "Host/Cluster",
"setCluster",
"org.apache.catalina.Cluster");为Host添加生命周期
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Host/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Host/Listener");
digester.addSetNext(prefix + "Host/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");为Host添加安全配置
1
2
3
4
5
6
7
8
9digester.addRuleSet(new RealmRuleSet(prefix + "Host/"));
digester.addObjectCreate(prefix + "Host/Valve",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Host/Valve");
digester.addSetNext(prefix + "Host/Valve",
"addValve",
"org.apache.catalina.Valve");
Context的解析
ContextRuleSet类中包含Context的解析
Catalina中Context配置并非来源于一处,此处仅介绍server.xm中的配置,大多数情况下,不需要在server.xml中配置Context,而是由HostConfig自动扫描部署目录,以context.xml文件为基础进行解析创建。
Context实例化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18//使用server.xml创建时,create为true;通过HostConfig创建时create为false
if (create) {
digester.addObjectCreate(prefix + "Context",
"org.apache.catalina.core.StandardContext", "className");
digester.addSetProperties(prefix + "Context");
} else {
digester.addRule(prefix + "Context", new SetContextPropertiesRule());
}
if (create) {
digester.addRule(prefix + "Context",
new LifecycleListenerRule
("org.apache.catalina.startup.ContextConfig",
"configClass"));
digester.addSetNext(prefix + "Context",
"addChild",
"org.apache.catalina.Container");
}为Context添加生命周期监听器
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Context/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Listener");
digester.addSetNext(prefix + "Context/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");为Context指定类加载器
1
2
3
4
5
6
7
8//默认为org.apache.catalina.loader.WebappLoader
digester.addObjectCreate(prefix + "Context/Loader",
"org.apache.catalina.loader.WebappLoader",
"className");
digester.addSetProperties(prefix + "Context/Loader");
digester.addSetNext(prefix + "Context/Loader",
"setLoader",
"org.apache.catalina.Loader");为Context添加会话管理器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 默认为org.apache.catalina.session.StandardManager
digester.addObjectCreate(prefix + "Context/Manager",
"org.apache.catalina.session.StandardManager",
"className");
digester.addSetProperties(prefix + "Context/Manager");
digester.addSetNext(prefix + "Context/Manager",
"setManager",
"org.apache.catalina.Manager");
// 指定会话存储方式
digester.addObjectCreate(prefix + "Context/Manager/Store",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Manager/Store");
digester.addSetNext(prefix + "Context/Manager/Store",
"setStore",
"org.apache.catalina.Store");
//指定会话标识生成器
digester.addObjectCreate(prefix + "Context/Manager/SessionIdGenerator",
"org.apache.catalina.util.StandardSessionIdGenerator",
"className");
digester.addSetProperties(prefix + "Context/Manager/SessionIdGenerator");
digester.addSetNext(prefix + "Context/Manager/SessionIdGenerator",
"setSessionIdGenerator",
"org.apache.catalina.SessionIdGenerator");为Context添加初始化参数
可以在context.xml文件中添加初始化参数,已实现所有Web应用中的复用,而不必每个Web应用重复配置
1
2
3
4
5
6digester.addObjectCreate(prefix + "Context/Parameter",
"org.apache.tomcat.util.descriptor.web.ApplicationParameter");
digester.addSetProperties(prefix + "Context/Parameter");
digester.addSetNext(prefix + "Context/Parameter",
"addApplicationParameter",
"org.apache.tomcat.util.descriptor.web.ApplicationParameter");为Context添加安全配置以及Web资源配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33digester.addRuleSet(new RealmRuleSet(prefix + "Context/"));
digester.addObjectCreate(prefix + "Context/Resources",
"org.apache.catalina.webresources.StandardRoot",
"className");
digester.addSetProperties(prefix + "Context/Resources");
digester.addSetNext(prefix + "Context/Resources",
"setResources",
"org.apache.catalina.WebResourceRoot");
digester.addObjectCreate(prefix + "Context/Resources/PreResources",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Resources/PreResources");
digester.addSetNext(prefix + "Context/Resources/PreResources",
"addPreResources",
"org.apache.catalina.WebResourceSet");
digester.addObjectCreate(prefix + "Context/Resources/JarResources",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Resources/JarResources");
digester.addSetNext(prefix + "Context/Resources/JarResources",
"addJarResources",
"org.apache.catalina.WebResourceSet");
digester.addObjectCreate(prefix + "Context/Resources/PostResources",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Resources/PostResources");
digester.addSetNext(prefix + "Context/Resources/PostResources",
"addPostResources",
"org.apache.catalina.WebResourceSet");为Context添加资源链接
1
2
3
4
5
6
7//用于J2EE命名服务
digester.addObjectCreate(prefix + "Context/ResourceLink",
"org.apache.tomcat.util.descriptor.web.ContextResourceLink");
digester.addSetProperties(prefix + "Context/ResourceLink");
digester.addRule(prefix + "Context/ResourceLink",
new SetNextNamingRule("addResourceLink",
"org.apache.tomcat.util.descriptor.web.ContextResourceLink"));为Context添加拦截器Value
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Context/Valve",
null, // MUST be specified in the element
"className");
digester.addSetProperties(prefix + "Context/Valve");
digester.addSetNext(prefix + "Context/Valve",
"addValve",
"org.apache.catalina.Valve");为Context添加守护资源配置
1
2
3
4
5
6
7
8
9
10
11
12
13<!-- context.xml -->
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
</Context>
1 | //WatchedResource标签用于为Context添加监视器,当这些资源发生变更时,Web应用将会被重新加载,默认为WEB-INF/web.xml |
为Context添加Cookie处理器
1
2
3
4
5
6
7digester.addObjectCreate(prefix + "Context/CookieProcessor",
"org.apache.tomcat.util.http.Rfc6265CookieProcessor",
"className");
digester.addSetProperties(prefix + "Context/CookieProcessor");
digester.addSetNext(prefix + "Context/CookieProcessor",
"setCookieProcessor",
"org.apache.tomcat.util.http.CookieProcessor");