context
一个context代表一个web应用,它运行在特定的虚拟主机中,每个web应用要么是一个war文件,要么是一个符合规范的目录。一般HTTP请求路径中带有requestURI,我们可以从requestURI中获取上下文路径,根据上下文路径可以选择适合的web应用程序来处理这个请求。你还可以定义多个context,但每个context的名称必须唯一。
context一般会出现在以下三个地方:
(1)、放到web应用的/META-INF/context.xml中,此时如果copyXML属性为true,会将其被拷贝到 $CATALINA_BASE/conf/[enginename]/[hostname]/ 目录中,并命名为应用名;
(2)、直接放到$CATALINA_BASE/conf/[enginename]/[hostname]/ 目录下,该文件将总是优先于/META-INF/context.xml部署;
(3)、server.xml文件的Host元素下面
并不推荐将context直接写在server.xml文件中,因为修改server.xml文件不会导致重新部署,必须重新启动tomcat才会生效,但是在server.xml文件中可以定义多个context元素,其他两种情况不允许。此外,$CATALINA_BASE/conf/context.xml这个文件会被所有web应用加载,$CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default会被同一台主机的所有web应用加载。
StandardContext
standardContext是Context的标准实现,下面来看看这个类在初始化和启动的时候都做了些什么事。
initInternal
tomcat在启动的过程中是怎么从host过渡到context的?记得在hostconfig类中在部署web应用的时候会调用host.addChild()方法将context挂在host名下作为它的子容器
从上图可以看出在调用host.addChild()方法时触发了child的start方法,再生命周期循环到context的initInternal方法
看看这个方法的代码:
- protected void initInternal() throws LifecycleException {
- super.initInternal();
- if (processTlds) {
- this.addLifecycleListener(new TldConfig());
- }
- // Register the naming resources
- if (namingResources != null) {
- namingResources.init();
- }
- // Send j2ee.object.created notification
- if (this.getObjectName() != null) {
- Notification notification = new Notification("j2ee.object.created",
- this.getObjectName(), sequenceNumber.getAndIncrement());
- broadcaster.sendNotification(notification);
- }
- }
startInternal
比initInternal方法复杂得多,大体上做了以下几件事:
1、构建webappclassLoader;
2、从CharsetMapperDefault.properties中获取字符集,默认只支持两种en=ISO-8859-1和fr=ISO-8859-1
3、创建工程目录workdir=work/enginename/hostname/contextname
4、context启动完后,随即启动它的附属组件:loader,logger,pipeline,sessionManager等
5、触发contextconfig.lifecycleEvent调用contextConfig.lifecycleEvent处理web.xml配置文件
5、启动它的每个wrapper子容器
6、加载和初始始化那些标识"load on startup"的servlet类
配置
cookies:是否启用cookies,默认为true
docBase:web应用所在的目录,当context定义在server.xml时这个值必须设置,当docbase不在webapps目录下时也必须设置
path:web应用的上下文路径,同一台主机必须唯一,如果为空串则可以处理所有请求
unpackWAR:Standard Context中特有的属性,如果为false表示war包不会被解压,默认为true
workDir:Standard Context中特有的属性,JSP等会被编译在这个目录
reloadable:如果你需要监视 /WEB-INF/classes/ 和/WEB-INF/lib目录下的文件,就把它设置为true吧,变化后会重载web应用,开发的时候很有用,默认为false,常常提到的重新部署和重新加载,两者之间的区别后续再分析。