不像其他类型的容器,一个StandardContext必须需要一个监听器。这个监听器配置StandardContext的实例并且一旦成功的完成这些,就设置StandardContext的configured变量为true。在前面的章节中,我们使用SimpleContextConfig类作为StandardContext的监听器。这个类非常简单,其唯一目的是设置configured变量,这样StandardContext的start方法可以继续运行。
在一个真实的Tomcat部署中,StandardContext的标准监听器是org.apache.catalina.startup.ContextConfig的一个实例。不像底下的SimpleContextConfig类,ContextConfig举足轻重,没有它 StandardContext不能独活。例如,与StandardContext相关联的ContextConfig实例在StandardContext的管道中配置了一个authenticcator值。也给pipeline设置了一个certificate值(是org.apache.catalina.values.CertificateValue类型)
但是更重要的,ContextConfig实例也读取和解析默认的web.xml文件和应用程序的web.xml文件并将XML元素转化为对应的Java对象。默认的web.xml文件位于CATALIAN_HOME的conf目录下。其定义和映射了默认的servlet,使用MIME类型映射了文件表达式,定义了默认的回话超时,并罗列了欢迎文件。你应该现在打开文件来看看其内容。
应用程序的web.xml文件是此应用程序的配置文件,在应用程序中的WEB-INF目录下加载。两个文件都不是必须的。即使没有一个文件找到,ContextConfig也将继续运行。
ContextConfig为每个Servet元素创建了一个StandardWrapper实例。因此,就如这章的应用程序中配置是很简单的额。你不再需要实例化一个wrapper。
因此,在你的bootStarp类中的某个地方,你必须实例化ContextConfig类并调用LifeCycle接口的addLifecycleListener方法将其添加到StandardContext中。
LifecycleListener listener = new ContextConfig();
((Lifecycle) context).addLifecycleListener(listener);
当StandardContext触发以下事件:
BEFORE_START_EVENT
START_EVENT
AFTER_START_EVENT
当停止的时候,StandardContext触发以下事件:
BEFORE_STOP_EVENT
STOP_EVENT
AFTER_STOP_EVENT
ContextConfig响应两个事件:START_EVENT和STOP_EVENT。每次StandardContext触发一个事件的时候,lifecycleEvent方法调用一次。其代码清单如下。其中我们添加了一些内容,这样其stop方法很容易理解。
public void lifecycleEvent(LifecycleEvent event) {
// Identify the context we are associated with
try {
context = (Context) event.getLifecycle();
if (context instanceof StandardContext) {
int contextDebug = ((StandardContext) context).getDebug();
if (contextDebug > this.debug)
this.debug = contextDebug;
}
}
catch (ClassCastException e) {
log(sm.getString("contextConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.START_EVENT))
start();
else if (event.getType().equals(Lifecycle.STOP_EVENT))
stop();
}
就如这个方法的结尾显示的那样,要不调用start方法要不调用stop方法。start方法的代码清单如15.12所示。注意这个方法内部调用了defaultConfig方法和applicationConfig方法。会在后面章节中解释。
Listing 15.12: The start method of ContextConfig
private synchronized void start() {
if (debug > 0)
log(sm.getString("ContextConfig.start"));
// reset the configured boolean
context.setConfigured(false);
// a flag that indicates whether the process is still
// going smoothly
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);
}
}
// Process the default and application web.xml files
defaultConfig();
applicationConfig();
if (ok) {
validateSecurityRoles();
}
// Scan tag library descriptor files for additional listener classes
if (ok) {
try {
tldScan();
}
catch (Exception e) {
log(e.getMessage(), e);
ok = false;
}
}
// Configure a certificates exposer valve, if required
if (ok)
certificatesConfig();
// Configure an authenticator if we need one
if (ok)
authenticatorConfig();
// Dump the contents of this pipeline if requested
if ((debug >= 1) && (context instanceof ContainerBase)) {
log("Pipline Configuration:");
Pipeline pipeline = ((ContainerBase) context).getPipeline();
Valve valves[] = null;
if (pipeline != null)
valves = pipeline.getValves();
if (valves != null) {
for (int i = 0; i < valves.length; i++) {
log(" " + valves[i].getInfo());
}
}
log("======================");
}
// Make our application available if no problems were encountered
if (ok)
context.setConfigured(true);
else {
log(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}
the defaultConfig Method