StandardWrapper、StandardContext、StandardHost、StandardEngine
四类标准容器均继承于基本容器ContainerBase
。
4类容器启动请求流转方向 & 启动时pipeline调用方向
Engine & Host
Context容器的父容器通常是Host容器,也有可能是其他实现。Engine容器表示Cataline的整个servlet引擎。如果使用了Engine容器,那么它总是处于容器层级的最顶层。添加到Engine容器中的子容器通常是Host | Context的实现。
当部署Tomcat需要支持多个虚拟机的时候,就需要Engine容器。
// docBase
/Users/zhfeng/code/Tomcat-Study/webapps/app1
// appBase
webapps/app1
Host容器的必要性
StandardServer
org.apache.catalina.server接口的实例表示Catalina的整个servlet引擎,囊括了所有的组件。服务器组件使用一种优雅的方式来启动/关闭整个系统,不需要再对连接器和容器分别启动/关闭。
当启动服务器组件时,会启动其中所有的组件,然后她就无限期地等待关闭命令。如果想要关闭系统,可以向指定端口发送一条关闭命令,就会关闭所有组件。
服务器组件使用了另一个组件(即服务组件)来包含其他组件,如一个容器组件&一个/多个连接器组件。
服务器组件,实现org.apache.catalina.server接口,主要功能:服务器关闭功能 & 与Server.xml 。
StandardService
StandardService是服务组件,其中只包括两种组件:Connector组件 & Servlet 组件。
Digester
与其他类型的容器不同,StandardContext实例必须有一个监听器,这个监听器会负责配置StandardContext实例,设置成功后会将StandardContext实例的变量configured设置为true。
在Tomcat实例部署中,StandardContext类的标准监听器是ContextConfig类的一个实例。其最重要的功能是读取&解析默认的web.xml文件和应用程序自定义的web.xml文件,将XML元素转换为Java对象。默认的web.xml文件位于Catalina_Home目录下的conf目录中。
应用程序中自定义的web.xml文件位于WEF-INF目录中。
StandardContext:
public synchronized void start() throws LifecycleException {
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
if (debug >= 1)log("Processing start(), current available=" + getAvailable());
setAvailable(false);
setConfigured(false);
boolean ok = true;
...
// Initialize character set mapper
getCharsetMapper();
//创建 ApplicationContext上下文
postWorkDirectory();
...
// Binding thread
ClassLoader oldCCL = bindThread();
// Standard container startup
if (debug >= 1)log("Processing standard container startup");
if (ok) {
try {
addDefaultMapper(this.mapperClass);
started = true;
// Start our subordinate components, if any
// 创建WebappClassLoader 载入器。
// 处理 /WEB-INF/classes /WEB-INF/lib目录下的类文件
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).start();
}
...
// Start our Mappers, if any
Mapper mappers[] = findMappers();
for (int i = 0; i < mappers.length; i++) {
if (mappers[i] instanceof Lifecycle){
((Lifecycle) mappers[i]).start();
}
}
System.out.println("start StandardContext 6 ...");
// Start our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle){
((Lifecycle) children[i]).start();
}
}
// Start the Valves in our pipeline (including the basic),
// if any
if (pipeline instanceof Lifecycle){
((Lifecycle) pipeline).start();
}
lifecycle.fireLifecycleEvent(START_EVENT, null);
...
} finally {
// Unbinding thread
unbindThread(oldCCL);
}
}
...
}
ContextConfig:
private synchronized void start() {
context.setConfigured(false);
ok = true;
// Set properties based on DefaultContext
Container container = context.getParent();
if( !context.getOverride() ) {
if( container instanceof Host ) {
((Host)container).importDefaultContext(context);
container = container.getParent();
}
if( container instanceof Engine ) {
((Engine)container).importDefaultContext(context);
}
}
// 处理默认配置 System.getProperty("catalina.base")+/conf/web.xml
defaultConfig();
//处理应用程序web.xml /StandardContext.parent.name/StandardContext.name/WEB-INF/web.xml
applicationConfig();
...
// Make our application available if no problems were encountered
if (ok)
context.setConfigured(true);
else {
log(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}