首页 > 代码库 > How tomcat works 读书笔记十二 StandardContext 上
How tomcat works 读书笔记十二 StandardContext 上
在tomcat4中,StandardContext.java是最大的一个类,有117k。废话不说,开始分析吧。
其实要分析StandardContext,也就主要分析两个方法,一个start,一个invoke。
先说available,它表示了StandardContext是否可用,初始值为false。若StandardContext启动成功,其值就变为true;另外各种原因都会导致StandardContext启动失败,这个时候available就是false。
configured,表明configured是否正确配置。与available不同的是,对configured这个参数我们采用了观察者模式。
lifecycle.fireLifecycleEvent(START_EVENT, null);
不过为什么configured使用了观察者模式,而available没有用呢?
2 设置available与configured的值为false;
4 配置载入器 setLoader(new WebappLoader(getParentClassLoader()));
5 配置Session setManager(new StandardManager());
6 初始化字符集映射器 getCharsetMapper(); 这里面的详细代码我也没有研究过
7 启动load,loger,mapper
loadOnStartup(findChildren());这行代码干的事呀。至于postWelcomeFiles倒像是设定什么属性。
如果confired为false就调用stop();
13 触发AFTER_START_EVENT事件 lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
首先会检查程序是否正在重载:
super.invoke(request, response);
在 Tomcat5 中,StandardContext 并没有提供 invoke 方法的实现,因此它会执行 ContainerBase 的 invoke 方法。检查应用程序加载的任务在StandardContextValve 类的 invoke 方法中完成。
基础阀干的事情就是获得Wrapper
根据uri获得Wrapper就是应用一系列的匹配规则获得Wrapper。
你可能会问,上下文容器时如何获得 Servlet 映射的?看Bootstrap。
现在就有几个问题了,生产映射器哪家强?映射器从哪里来?
来,听本座给你一一道来..
在StandardContext的start方法中
调用了
mapper.setContainer((Container) this);
可见映射器与容器是双向关联的。(并且只能与Context级别的容器关联)
为什么?单向关联不行么?
(某个协议下的)映射器根据uri返回相应的Wrapper,如何映射器"不知道"Context容器,它怎么查找众多的子容器?用for循环么?
所有的子容器是存放在ContainerBase中的
protected HashMap<String, Container> children = new HashMap<String, Container>();
这一节就先到这里,下面我们在说tomcat4对重载的支持和在Tomcat5中的backgroundProcess方法。
其实要分析StandardContext,也就主要分析两个方法,一个start,一个invoke。
两个变量
这里首先咱们得说两个boolean型的变量available,configured。先说available,它表示了StandardContext是否可用,初始值为false。若StandardContext启动成功,其值就变为true;另外各种原因都会导致StandardContext启动失败,这个时候available就是false。
configured,表明configured是否正确配置。与available不同的是,对configured这个参数我们采用了观察者模式。
public class SimpleContextConfig implements LifecycleListener { public void lifecycleEvent(LifecycleEvent event) { if (Lifecycle.START_EVENT.equals(event.getType())) { Context context = (Context) event.getLifecycle(); context.setConfigured(true); } } }在StandardContext配置完成后调用
lifecycle.fireLifecycleEvent(START_EVENT, null);
不过为什么configured使用了观察者模式,而available没有用呢?
start方法
1 lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); 触发BEFORE_START_EVENT事件2 设置available与configured的值为false;
setAvailable(false); setConfigured(false);3 配置资源 (这部分我也不是太懂)
4 配置载入器 setLoader(new WebappLoader(getParentClassLoader()));
5 配置Session setManager(new StandardManager());
6 初始化字符集映射器 getCharsetMapper(); 这里面的详细代码我也没有研究过
7 启动load,loger,mapper
((Lifecycle) loader).start(); ((Lifecycle) logger).start(); ((Lifecycle) mappers[i]).start();8 启动子容器
Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); }9 启动管道
if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start();10 触发START_EVENT,注意呀 观察者模式,SimpleContextConfig, configured会被设置为true
// Notify our interested LifecycleListeners // 会调用SimpleContextConfig的lifecycleEvent lifecycle.fireLifecycleEvent(START_EVENT, null);11 启动session
//session部分 if ((manager != null) && (manager instanceof Lifecycle)) ((Lifecycle) manager).start();12 (书上说)检查confired的值,postWelcomeFiles会载入需要提前载入的子容器,StandardContext的子容器能有什么?StandardWrapper呗。
if (!getConfigured()) ok = false; if (ok) { postWelcomeFiles(); }问题是加载需要提前载入的子容器是
loadOnStartup(findChildren());这行代码干的事呀。至于postWelcomeFiles倒像是设定什么属性。
如果confired为false就调用stop();
if (ok) { setAvailable(true); } else { try { stop(); } catch (Throwable t) { log(sm.getString("standardContext.startCleanup"), t); } setAvailable(false); }stop里面具体的代码就不说了。
13 触发AFTER_START_EVENT事件 lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
invoke方法
StandardContext的invoke方法会在两种情况下被调用。至于有哪两种自己想。首先会检查程序是否正在重载:
while (getPaused()) { //getPaused如果返回true 就说明正在重载 try { Thread.sleep(1000); } catch (InterruptedException e) { ; } }然后调用父类,也就是ContainerBase的invoke
super.invoke(request, response);
在 Tomcat5 中,StandardContext 并没有提供 invoke 方法的实现,因此它会执行 ContainerBase 的 invoke 方法。检查应用程序加载的任务在StandardContextValve 类的 invoke 方法中完成。
StandardContextMapper类
上面到StandardContextValve类的invoke 方法,接着就是调用管道的invoke,然后基础阀的invoke(基础阀是哪个类,什么时候注入的,还记的吗)基础阀干的事情就是获得Wrapper
Context context = (Context) getContainer(); wrapper = (Wrapper) context.map(request, true);接着在ContainerBase的map中先获得相应协议(http还是https)的映射器,再用映射器的map方法根据request的uri获得Wrapper。
根据uri获得Wrapper就是应用一系列的匹配规则获得Wrapper。
你可能会问,上下文容器时如何获得 Servlet 映射的?看Bootstrap。
现在就有几个问题了,生产映射器哪家强?映射器从哪里来?
来,听本座给你一一道来..
在StandardContext的start方法中
调用了
addDefaultMapper(this.mapperClass); //private String mapperClass = "org.apache.catalina.core.StandardContextMapper";StandardContext会调用父类的addDefaultMapper。这里面,默认的协议是http
Class<?> clazz = Class.forName(mapperClass); Mapper mapper = (Mapper) clazz.newInstance(); mapper.setProtocol("http"); addMapper(mapper);在addMapper中
mapper.setContainer((Container) this);
可见映射器与容器是双向关联的。(并且只能与Context级别的容器关联)
为什么?单向关联不行么?
(某个协议下的)映射器根据uri返回相应的Wrapper,如何映射器"不知道"Context容器,它怎么查找众多的子容器?用for循环么?
所有的子容器是存放在ContainerBase中的
protected HashMap<String, Container> children = new HashMap<String, Container>();
这一节就先到这里,下面我们在说tomcat4对重载的支持和在Tomcat5中的backgroundProcess方法。
How tomcat works 读书笔记十二 StandardContext 上
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。