StandardContext类
Context实例表示一个web应用程序。包含一个或者多个Wrapper实例,每个wrapper都代表一个Servlet。
StandardContext是Context的标准实现,今天说一下工作机制。
StandardContext的配置
创建实例之后,必须调用start()方法,为引入的每个HTTP请求提供服务。可能由于某种原因StandardContext对象可能启动失败。设置available = false 是否可用。
配置StandardContext正确之后才可以 解析读取web.xml。
configured属性是一个布尔变量。表明StandardContext实例是否正确设置。(通过事件监听器来设置,调用start()触发生命周期事件,该事件调用监听器,如果配置成功,监听器设置configured为true)
StandardContext的构造函数
public StandardContext(){
super();
pipeline.setBasic(new StandardContextValve());
namingResources.setContainer(this);
}
设置管道对象的基础阀。该阀会处理连接器,收到的所有HTTP请求。
启动StandardContext实例
start()方法会初始化StandardContext对象,用生命周期监听器配置实例。
1.触发BEFORE_START事件
2.将availability属性设置为false
3.将configured属性设置为false
4.配置资源
5.设置载入器
6.设置session管理器
7.初始化字符集映射器
8.启动与该Context容器相关联的组件
9.启动子容器
10.启动管道对象
11.启动session管理器
12.触发START事件,这里监听器执行一些配置操作。设置成功,configured = true;
13.检查configured若为true,调用postWelcomePages(),载入那些需要在启动就载入的子容器。即,Wrapper实例。将availability = true。false的话调用stop()
14触发AFTER_START事件
invoke方法
StandardContext的invoke()是由,连接器来调用(或StandardContext是HOST的子容器,是由主机调)。
该方法,首先会检查应用程序是否正在重载过程。若是则等待,然后调用父类ContainerBase的invoke方法。
调用getPaused(),返回true,表示正在重载。tomcat5移到了StandardContextValue类中做。
StandardContextMapper类
对于每个引入的HTTP请求,都会调用StandardContext实例,的管道对象,的基础阀的invoke()。
该映射器,就是用来找一个合适的wrapper实例。
通过setContainer()方法,传入一个容器的实例,将映射器与容器关联。Mapper接口的实现就是该类。只能与Context级别的容器关联。
public void setContainer(Container container){
if(!(cibntainer insatnceof StandardContext))
throw new ....;
context = (StandardContext) container;
}
映射器重要方法map(),返回处理HTTP请求的容器
public Container map(Request request , boolean update)
Mapper mapper = findMapper(request.getRequest().getProtool());
if(mapper ==null) return null;
return (mapper.map(request , update))
对重载的支持
SandardContext类定义了reloadable属性来指定该应用程序启动了重载功能。启用后,当web.xml或者WEB-INF/classes目录下,其中一个文件被重新编译,应用程序会重载。
StandardContext通过载入器,实现。该对象,的webapploader类实现了loader接口。使用另一个线程检查WEB-INF目录中所有类的JAR文件的时间戳。
webapploader的reloadable属性,从false修改为true,则会调用threadStart()方法,启动一个专用线程,监听时间戳。从true修改为false,则调threadStop(),终止该线程。
backgroundProcess()方法
Context容器运行需要其他组件支持。组件需要各自线程执行一些后台处理任务。载入器,监听时间戳。session定期检测是否过期。
为了节省资源,所有后台处理共享同一线程。如果某个组件或servlet周期性执行一个操作。只需要将代码卸载backgroundProcess方法中。
这个共享线程在ContainerBase对象的start()方法,调用threadStart()中创建。