第12章 StandardContext类
一个Context实例可以表示一个具体的WEB应用程序,其中可包含多个Wrappe实例。
12.1 StandardContext的配置
们得说两个boolean型的变量available,configured。先说available,它表示了StandardContext是否可用,初始值为false。若StandardContext启动成功,其值就变为true;另外各种原因都会导致StandardContext启动失败,这个时候available就是false。
configured,表明configured是否正确配置。与available不同的是,对configured这个参数我们采用了观察者模式。
12.1.1 StandardContext类的构造函数
public StandardContext(){
super();
pipeline.setBasic(new StandardContextValve());
}
构造函数中最重要的事情是为StandardContext实例的管道对象设置基础阀,该基础阀会处理从连接器中接收到的每个HTTP请求。
12.1.2 启动StandardContext实例
start()方法会初始化StandardContext对象,用生命周期监听器配置StandardContext实例。当配置成功后,监听器会讲其configured属性置为true。最后,start()方法会将available属性设置为true或者false,true表明StandContext对象设置正确,与其相关联的子容器和组件都正确启动,因此,StandContext实例可以准备为引入的HTTP请求提供服务了,若期间发生了错误,则available会被置为false。
start方法完成顺序:
1. 出发BEFORE_START事件;
2. 将availability属性设置为false;
3. 将configured属性设置为false;
4. 配置资源;
5. 设置载入器;
6. 设置session管理器;
7. 初始化字符集映射器;
8. 启动与该context容器相关的组件;
9. 启动子容器;
10. 启动管道对象;
11. 启动session管理器;
12. 触发START事件,在这里监听器(ContextConfig实例)会执行一些配置操作,若设置成功,ContextConfig实例会将StandardContext实例的configured变量设置成true。
13. 检查configured属性的值,若为true,则调用postWelcomePages方法,载入那些需要再启动时就载入的子容器,既Wrapper实例,将availability设置为true.若configured变量为false,则调用stop()方法;
14. 触发AFTER_START事件。
12.2 StandardContextMapper类
对于每个引入的HTTP请求,都会调用基础阀的invoke方法来处理,然后通过映射器获取相对应的servlet实例。
下面来介绍一些映射器组件:
ContainerBase类是StandardContext类的父类,ContainerBase定义addDefaultMapper方法来添加一个默认的映射器。
protected void addDefaultMapper(String mapperClass){
if(mapperClass == null){
return;
}
if(mapperClass.size()>=1){
return;
}
try{
Class clazz = class.forName(mapperClass);
Mapper mapper = (Mapper)clazz.newInstance();
mapper.setProtocol("HTTP");
addMapper(mapper);
}catch(){
}
}
StandardContext类在其start方法中调用addDefaultMapper()方法,并传入默认映射器。
public synchronized void start() throws LifecycleException{
...
if(ok){
addDefaultMapper(this.mapperClass);
}
}
映射器中最重要的方法是map方法,该方法会返回用来处理HTTP请求的子容器
public Container map(Request request,boolean update);
12.4 对重载的支持
StandardContext类定义了reloadable属性来指明该应用程序是否启用了重载功能。当启用了重载功能后,当web.xml文件发生变化获取WEB/INF/classes目录下的其中一个文件被重新编译后,应用程序会重载。
public void setContainer(Container container) {
...
// Register with the new Container (if any)
if ((this.container != null) && (this.container instanceof Context)) {
setReloadable( ((Context) this.container).getReloadable() );
((Context) this.container).addPropertyChangeListener(this);
}
}
可见载入器的reloadable与它所绑定的容器的reloadable是一致的。
我们再看看载入器的setReloadable:
public void setReloadable(boolean reloadable) {
// Process this property change
boolean oldReloadable = this.reloadable;
this.reloadable = reloadable;
....
if (!started)
return;
if (!oldReloadable && this.reloadable) //
threadStart();
else if (oldReloadable && !this.reloadable)
threadStop();
}
若reloadable属性的值从false修改为true,则会调用threadStart方法;若reloadable属性的值从true修改为false,则会调用threadStop方法.threadStart()方法会启动一个专用的县城来不断检查WEB-INF目录下的类和JAR文件的时间戳。
再Tomcat5中,支持重载功能而进行检测时间戳的工作由backgroundProcess方法执行。