Servlet容器是tomcat的核心组件,所有基于jsp/servlet的Java web应用均需要依托servlet容器运行并对外提供服务。
tomcat本质上是一款servlet容器,因此Catalina是tomcat的核心,其它模块均为catalina提供支持。
Digester Catalina使用digester解析xml配置文件,并创建应用服务器。
digester主要有对象栈、匹配模式和处理规则三部分。
对象栈保存各个节点对象。 digest用法:
解析用的代码:
public static void ts1() throws IOException, SAXException { Digester digester=new Digester(); digester.setValidating(false); digester.setRulesValidation(true); digester.addObjectCreate("department",Department.class.getName()); digester.addSetProperties("department");//匹配到department节点时,设置对象属性.比如name,age等自定义属性自动装填。 digester.addObjectCreate("department/user",User.class.getName()); digester.addSetProperties("department/user"); digester.addSetNext("department/user","addUser",User.class.getName()); digester.addCallMethod("department/extension","putExtension",2); digester.addCallParam("department/extension/property-name",0); digester.addCallParam("department/extension/property-value",1); Department d= (Department) digester.parse(TestMain.class.getResourceAsStream("/test.xml")); System.out.println(d.getCode()); }
原文:
<?xml version="1.0" encoding="UTF-8" ?> <department> <user name="un1" code="uc1"></user> <user name="un2" code="uc2"></user> <extension> <property-name>director</property-name> <property-value>joke</property-value> </extension> </department>
Department和user是自定义的类,用于描述文件属性。
catalina类通过下面这个方法,创建了digester类。
protected Digester createStartDigester() { long t1 = System.currentTimeMillis(); Digester digester = new Digester(); digester.setValidating(false); digester.setRulesValidation(true); Map<Class<?>, List<String>> fakeAttributes = new HashMap(); List<String> attrs = new ArrayList(); attrs.add("className"); fakeAttributes.put(Object.class, attrs); digester.setFakeAttributes(fakeAttributes); digester.setUseContextClassLoader(true); digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");//创建server对象,如果有自定义className,则使用自定义的属性 digester.addSetProperties("Server");//装填属性 digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");//设置到catalina类中 digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl"); //创建Java EE企业命名上下文 digester.addSetProperties("Server/GlobalNamingResources"); digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResourcesImpl");//将其设置到server实例中 //为server创建声明周期监听器 digester.addObjectCreate("Server/Listener", (String)null, "className"); digester.addSetProperties("Server/Listener"); digester.addSetNext("Server/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //className指定LifecycleListener,Catalina默认配置了5个监听器。 //Apr 在server初始化前加载APR库,并在server停止后销毁 //VersionLogger server初始化前打印操作系统,jvm以及服务器版本信息 //JreMemoryLeakPreventionListener server初始化前调用,以解决单例对象创建导致的jvm内存泄漏以及锁文件问题 //GlobalResourcesLifecycleListener server启动时,将JNDI资源注册为MBean管理 //ThreadLocalLeakPrevention 用于在context停止时重建Executor池中 的线程,避免导致内存泄漏 //构建service实例 digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className"); digester.addSetProperties("Server/Service"); digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service");//把实例添加到server中 //为service添加生命周期监听器,默认情况下,Catalina未指定service监听器 digester.addObjectCreate("Server/Service/Listener", (String)null, "className"); digester.addSetProperties("Server/Service/Listener"); digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //为service添加Executor digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className"); digester.addSetProperties("Server/Service/Executor"); digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor"); //为service添加connector,排除executor和sslImplementationName digester.addRule("Server/Service/Connector", new ConnectorCreateRule()); digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName", "protocol"})); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector"); //为connector添加虚拟主机SSL配置 digester.addObjectCreate("Server/Service/Connector/SSLHostConfig", "org.apache.tomcat.util.net.SSLHostConfig"); digester.addSetProperties("Server/Service/Connector/SSLHostConfig"); digester.addSetNext("Server/Service/Connector/SSLHostConfig", "addSslHostConfig", "org.apache.tomcat.util.net.SSLHostConfig"); digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate", new CertificateCreateRule()); digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate", new SetAllPropertiesRule(new String[]{"type"})); digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate", "addCertificate", "org.apache.tomcat.util.net.SSLHostConfigCertificate"); digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf", "org.apache.tomcat.util.net.openssl.OpenSSLConf"); digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf"); digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf", "setOpenSslConf", "org.apache.tomcat.util.net.openssl.OpenSSLConf"); digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd", "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd"); digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd"); digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd", "addCmd", "org.apache.tomcat.util.net.openssl.OpenSSLConfCmd"); //为connector添加生命周期监听器 digester.addObjectCreate("Server/Service/Connector/Listener", (String)null, "className"); digester.addSetProperties("Server/Service/Connector/Listener"); digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //为connector添加升级协议,用于支持HTTP/2 digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol", (String)null, "className"); digester.addSetProperties("Server/Service/Connector/UpgradeProtocol"); digester.addSetNext("Server/Service/Connector/UpgradeProtocol", "addUpgradeProtocol", "org.apache.coyote.UpgradeProtocol"); //添加子元素解析规则 digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); digester.addRuleSet(new EngineRuleSet("Server/Service/")); digester.addRuleSet(new HostRuleSet("Server/Service/Engine/")); digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); this.addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/"); digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(this.parentClassLoader)); this.addClusterRuleSet(digester, "Server/Service/Engine/Cluster/"); long t2 = System.currentTimeMillis(); if(log.isDebugEnabled()) { log.debug("Digester for server.xml created " + (t2 - t1)); } return digester; }
Engine的解析
默认实现是StandardEngine,提供了默认配置EngineConfig用于打印engine的启动和停止日志。
public void addRuleInstances(Digester digester) { digester.addObjectCreate(this.prefix + "Engine", "org.apache.catalina.core.StandardEngine", "className"); digester.addSetProperties(this.prefix + "Engine"); digester.addRule(this.prefix + "Engine", new LifecycleListenerRule("org.apache.catalina.startup.EngineConfig", "engineConfigClass")); digester.addSetNext(this.prefix + "Engine", "setContainer", "org.apache.catalina.Engine");//添加到service实例中 //添加集群配置 digester.addObjectCreate(this.prefix + "Engine/Cluster", (String)null, "className"); digester.addSetProperties(this.prefix + "Engine/Cluster"); digester.addSetNext(this.prefix + "Engine/Cluster", "setCluster", "org.apache.catalina.Cluster"); //添加生命周期监听器 digester.addObjectCreate(this.prefix + "Engine/Listener", (String)null, "className"); digester.addSetProperties(this.prefix + "Engine/Listener"); digester.addSetNext(this.prefix + "Engine/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //添加安全配置 digester.addRuleSet(new RealmRuleSet(this.prefix + "Engine/")); digester.addObjectCreate(this.prefix + "Engine/Valve", (String)null, "className"); digester.addSetProperties(this.prefix + "Engine/Valve"); digester.addSetNext(this.prefix + "Engine/Valve", "addValve", "org.apache.catalina.Valve"); }
host解析
public void addRuleInstances(Digester digester) { digester.addObjectCreate(this.prefix + "Host", "org.apache.catalina.core.StandardHost", "className"); digester.addSetProperties(this.prefix + "Host");//注入属性 digester.addRule(this.prefix + "Host", new CopyParentClassLoaderRule()); digester.addRule(this.prefix + "Host", new LifecycleListenerRule("org.apache.catalina.startup.HostConfig", "hostConfigClass")); //添加监听器 digester.addSetNext(this.prefix + "Host", "addChild", "org.apache.catalina.Container"); //把它添加到engine中 digester.addCallMethod(this.prefix + "Host/Alias", "addAlias", 0);//添加别名 //添加集群,为Host digester.addObjectCreate(this.prefix + "Host/Cluster", (String)null, "className"); digester.addSetProperties(this.prefix + "Host/Cluster"); digester.addSetNext(this.prefix + "Host/Cluster", "setCluster", "org.apache.catalina.Cluster"); //添加生命周期管理 digester.addObjectCreate(this.prefix + "Host/Listener", (String)null, "className"); digester.addSetProperties(this.prefix + "Host/Listener"); digester.addSetNext(this.prefix + "Host/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //添加安全管理 digester.addRuleSet(new RealmRuleSet(this.prefix + "Host/")); digester.addObjectCreate(this.prefix + "Host/Valve", (String)null, "className"); digester.addSetProperties(this.prefix + "Host/Valve"); digester.addSetNext(this.prefix + "Host/Valve", "addValve", "org.apache.catalina.Valve"); }
context解析
create为true时,表示通过server.xml配置context。 create为false时,通过HostConfig创建context。
public void addRuleInstances(Digester digester) { if(this.create) { digester.addObjectCreate(this.prefix + "Context", "org.apache.catalina.core.StandardContext", "className"); digester.addSetProperties(this.prefix + "Context"); } else { digester.addRule(this.prefix + "Context", new SetContextPropertiesRule()); } if(this.create) { digester.addRule(this.prefix + "Context", new LifecycleListenerRule("org.apache.catalina.startup.ContextConfig", "configClass"));//生命周期监听器,用于详细配置context,如详细解析web.xml digester.addSetNext(this.prefix + "Context", "addChild", "org.apache.catalina.Container"); } digester.addObjectCreate(this.prefix + "Context/Listener", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Listener"); digester.addSetNext(this.prefix + "Context/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); //指定生命周期监听器 digester.addObjectCreate(this.prefix + "Context/Loader", "org.apache.catalina.loader.WebappLoader", "className"); digester.addSetProperties(this.prefix + "Context/Loader"); digester.addSetNext(this.prefix + "Context/Loader", "setLoader", "org.apache.catalina.Loader"); //指定类加载器 digester.addObjectCreate(this.prefix + "Context/Manager", "org.apache.catalina.session.StandardManager", "className"); digester.addSetProperties(this.prefix + "Context/Manager"); digester.addSetNext(this.prefix + "Context/Manager", "setManager", "org.apache.catalina.Manager"); digester.addObjectCreate(this.prefix + "Context/Manager/Store", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Manager/Store"); digester.addSetNext(this.prefix + "Context/Manager/Store", "setStore", "org.apache.catalina.Store"); digester.addObjectCreate(this.prefix + "Context/Manager/SessionIdGenerator", "org.apache.catalina.util.StandardSessionIdGenerator", "className"); digester.addSetProperties(this.prefix + "Context/Manager/SessionIdGenerator"); digester.addSetNext(this.prefix + "Context/Manager/SessionIdGenerator", "setSessionIdGenerator", "org.apache.catalina.SessionIdGenerator"); //会话管理器 digester.addObjectCreate(this.prefix + "Context/Parameter", "org.apache.tomcat.util.descriptor.web.ApplicationParameter"); digester.addSetProperties(this.prefix + "Context/Parameter"); digester.addSetNext(this.prefix + "Context/Parameter", "addApplicationParameter", "org.apache.tomcat.util.descriptor.web.ApplicationParameter"); //添加初始化参数,这个会导致应用与tomcat紧耦合(一般很少更换服务容器,所以这个其实没什么影响)。 digester.addRuleSet(new RealmRuleSet(this.prefix + "Context/")); digester.addObjectCreate(this.prefix + "Context/Resources", "org.apache.catalina.webresources.StandardRoot", "className"); digester.addSetProperties(this.prefix + "Context/Resources"); digester.addSetNext(this.prefix + "Context/Resources", "setResources", "org.apache.catalina.WebResourceRoot"); digester.addObjectCreate(this.prefix + "Context/Resources/PreResources", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Resources/PreResources"); digester.addSetNext(this.prefix + "Context/Resources/PreResources", "addPreResources", "org.apache.catalina.WebResourceSet"); digester.addObjectCreate(this.prefix + "Context/Resources/JarResources", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Resources/JarResources"); digester.addSetNext(this.prefix + "Context/Resources/JarResources", "addJarResources", "org.apache.catalina.WebResourceSet"); digester.addObjectCreate(this.prefix + "Context/Resources/PostResources", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Resources/PostResources"); digester.addSetNext(this.prefix + "Context/Resources/PostResources", "addPostResources", "org.apache.catalina.WebResourceSet"); //添加安全配置以及资源配置 digester.addObjectCreate(this.prefix + "Context/ResourceLink", "org.apache.tomcat.util.descriptor.web.ContextResourceLink"); digester.addSetProperties(this.prefix + "Context/ResourceLink"); digester.addRule(this.prefix + "Context/ResourceLink", new SetNextNamingRule("addResourceLink", "org.apache.tomcat.util.descriptor.web.ContextResourceLink")); //添加资源链接,用于Java EE 命名服务 digester.addObjectCreate(this.prefix + "Context/Valve", (String)null, "className"); digester.addSetProperties(this.prefix + "Context/Valve"); digester.addSetNext(this.prefix + "Context/Valve", "addValve", "org.apache.catalina.Valve"); //添加拦截器Value digester.addCallMethod(this.prefix + "Context/WatchedResource", "addWatchedResource", 0);//添加监视资源,这些资源发生变化时,web应用会重新加载,默认是web.xml digester.addCallMethod(this.prefix + "Context/WrapperLifecycle", "addWrapperLifecycle", 0);//为context添加生命周期监听器,添加到context包含的wrapper上 digester.addCallMethod(this.prefix + "Context/WrapperListener", "addWrapperListener", 0); digester.addObjectCreate(this.prefix + "Context/JarScanner", "org.apache.tomcat.util.scan.StandardJarScanner", "className"); digester.addSetProperties(this.prefix + "Context/JarScanner"); digester.addSetNext(this.prefix + "Context/JarScanner", "setJarScanner", "org.apache.tomcat.JarScanner"); digester.addObjectCreate(this.prefix + "Context/JarScanner/JarScanFilter", "org.apache.tomcat.util.scan.StandardJarScanFilter", "className"); digester.addSetProperties(this.prefix + "Context/JarScanner/JarScanFilter"); digester.addSetNext(this.prefix + "Context/JarScanner/JarScanFilter", "setJarScanFilter", "org.apache.tomcat.JarScanFilter"); //添加守护资源配置 digester.addObjectCreate(this.prefix + "Context/CookieProcessor", "org.apache.tomcat.util.http.Rfc6265CookieProcessor", "className"); digester.addSetProperties(this.prefix + "Context/CookieProcessor"); digester.addSetNext(this.prefix + "Context/CookieProcessor", "setCookieProcessor", "org.apache.tomcat.util.http.CookieProcessor"); } //添加cookie管理器
web应用加载是server启动的核心处理过程,Catalina通过Standard host、hostconfig,standardcontext、contextConfig、standardWrapper这5个类完成对web应用的加载。
StandardHost加载web应用(即standardContext)的入口有2个,其中一个入口是由生命周期管理接口调用start方法启动,这是配置context元素在host元素内(解析server.xml时会创建context),这种方式不好用,因为每部署一个web应用,都需要在这来配置。 另一个入口是HostConfig自动扫描部署目录,创建context实例并启动。
StandardHost启动加载过程:
HostConfig---- 它是一个LifecycleListener实现,由catalina添加到Host实例上。处理的生命周期事件包括Start_EVENT,PERIODIC_EVENT,STOP_EVENT。前两者与web应用部署密切相关,后者用于在Host停止时注销其对应的MBean。
START_EVENT事件 该事件在host启动时触发,完成服务器启动过程中的web应用部署(需要deployOnStartup为true,默认是true)。 · context描述文件部署:tomcat支持通过一个独立的Context描述文件来配置并启动web应用,配置方式如同server.xml中的context元素。配置文件的存储路径由host的xmlBase属性指定,默认为$CATALINA_BASE/conf/< Engine名称 >/host名称。 这个就会加载test/myApp目录下的应用,访问路径则path。
context的描述文件由hostConfig进行扫描和解析,而hostconfig会使用线程池同时解析多个context的xml文件。
而每个线程使用以下代码解析单个xml文件:
protected void deployDescriptor(ContextName cn, File contextXml) { HostConfig.DeployedApplication deployedApp = new HostConfig.DeployedApplication(cn.getName(), true); long startTime = 0L; if(log.isInfoEnabled()) { startTime = System.currentTimeMillis(); log.info(sm.getString("hostConfig.deployDescriptor", new Object[]{contextXml.getAbsolutePath()})); } Context context = null; boolean isExternalWar = false; boolean isExternal = false; File expandedDocBase = null; boolean var30 = false; label870: { boolean unpackWAR; File warDocBase; label871: { try { var30 = true; FileInputStream fis = new FileInputStream(contextXml); Throwable var11 = null; try { Object var12 = this.digesterLock; synchronized(this.digesterLock) { try { context = (Context)this.digester.parse(fis); } catch (Exception var49) { log.error(sm.getString("hostConfig.deployDescriptor.error", new Object[]{contextXml.getAbsolutePath()}), var49); } finally { this.digester.reset(); if(context == null) { context = new FailedContext(); } } } Class<?> clazz = Class.forName(this.host.getConfigClass()); LifecycleListener listener = (LifecycleListener)clazz.newInstance(); ((Context)context).addLifecycleListener(listener); ((Context)context).setConfigFile(contextXml.toURI().toURL()); ((Context)context).setName(cn.getName()); ((Context)context).setPath(cn.getPath()); ((Context)context).setWebappVersion(cn.getVersion()); if(((Context)context).getDocBase() != null) { File docBase = new File(((Context)context).getDocBase()); if(!docBase.isAbsolute()) { docBase = new File(this.host.getAppBaseFile(), ((Context)context).getDocBase()); } if(!docBase.getCanonicalPath().startsWith(this.host.getAppBaseFile().getAbsolutePath() + File.separator)) { isExternal = true; deployedApp.redeployResources.put(contextXml.getAbsolutePath(), Long.valueOf(contextXml.lastModified())); deployedApp.redeployResources.put(docBase.getAbsolutePath(), Long.valueOf(docBase.lastModified())); if(docBase.getAbsolutePath().toLowerCase(Locale.ENGLISH).endsWith(".war")) { isExternalWar = true; } } else { log.warn(sm.getString("hostConfig.deployDescriptor.localDocBaseSpecified", new Object[]{docBase})); ((Context)context).setDocBase((String)null); } } this.host.addChild((Container)context); } catch (Throwable var52) { var11 = var52; throw var52; } finally { if(fis != null) { if(var11 != null) { try { fis.close(); } catch (Throwable var48) { var11.addSuppressed(var48); } } else { fis.close(); } } } var30 = false; break label871; } catch (Throwable var54) { ExceptionUtils.handleThrowable(var54); log.error(sm.getString("hostConfig.deployDescriptor.error", new Object[]{contextXml.getAbsolutePath()}), var54); var30 = false; } finally { if(var30) { expandedDocBase = new File(this.host.getAppBaseFile(), cn.getBaseName()); if(((Context)context).getDocBase() != null && !((Context)context).getDocBase().toLowerCase(Locale.ENGLISH).endsWith(".war")) { expandedDocBase = new File(((Context)context).getDocBase()); if(!expandedDocBase.isAbsolute()) { expandedDocBase = new File(this.host.getAppBaseFile(), ((Context)context).getDocBase()); } } boolean unpackWAR = this.unpackWARs; if(unpackWAR && context instanceof StandardContext) { unpackWAR = ((StandardContext)context).getUnpackWAR(); } if(isExternalWar) { if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } } else { if(!isExternal) { File warDocBase = new File(expandedDocBase.getAbsolutePath() + ".war"); if(warDocBase.exists()) { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(warDocBase.lastModified())); } else { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(0L)); } } if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } if(!isExternal) { deployedApp.redeployResources.put(contextXml.getAbsolutePath(), Long.valueOf(contextXml.lastModified())); } } this.addGlobalRedeployResources(deployedApp); } } expandedDocBase = new File(this.host.getAppBaseFile(), cn.getBaseName()); if(((Context)context).getDocBase() != null && !((Context)context).getDocBase().toLowerCase(Locale.ENGLISH).endsWith(".war")) { expandedDocBase = new File(((Context)context).getDocBase()); if(!expandedDocBase.isAbsolute()) { expandedDocBase = new File(this.host.getAppBaseFile(), ((Context)context).getDocBase()); } } unpackWAR = this.unpackWARs; if(unpackWAR && context instanceof StandardContext) { unpackWAR = ((StandardContext)context).getUnpackWAR(); } if(isExternalWar) { if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } } else { if(!isExternal) { warDocBase = new File(expandedDocBase.getAbsolutePath() + ".war"); if(warDocBase.exists()) { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(warDocBase.lastModified())); } else { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(0L)); } } if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } if(!isExternal) { deployedApp.redeployResources.put(contextXml.getAbsolutePath(), Long.valueOf(contextXml.lastModified())); } } this.addGlobalRedeployResources(deployedApp); break label870; } expandedDocBase = new File(this.host.getAppBaseFile(), cn.getBaseName()); if(((Context)context).getDocBase() != null && !((Context)context).getDocBase().toLowerCase(Locale.ENGLISH).endsWith(".war")) { expandedDocBase = new File(((Context)context).getDocBase()); if(!expandedDocBase.isAbsolute()) { expandedDocBase = new File(this.host.getAppBaseFile(), ((Context)context).getDocBase()); } } unpackWAR = this.unpackWARs; if(unpackWAR && context instanceof StandardContext) { unpackWAR = ((StandardContext)context).getUnpackWAR(); } if(isExternalWar) { if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } } else { if(!isExternal) { warDocBase = new File(expandedDocBase.getAbsolutePath() + ".war"); if(warDocBase.exists()) { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(warDocBase.lastModified())); } else { deployedApp.redeployResources.put(warDocBase.getAbsolutePath(), Long.valueOf(0L)); } } if(unpackWAR) { deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(), Long.valueOf(expandedDocBase.lastModified())); this.addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), (Context)context); } else { this.addWatchedResources(deployedApp, (String)null, (Context)context); } if(!isExternal) { deployedApp.redeployResources.put(contextXml.getAbsolutePath(), Long.valueOf(contextXml.lastModified())); } } this.addGlobalRedeployResources(deployedApp); } if(this.host.findChild(((Context)context).getName()) != null) { this.deployed.put(((Context)context).getName(), deployedApp); } if(log.isInfoEnabled()) { log.info(sm.getString("hostConfig.deployDescriptor.finished", new Object[]{contextXml.getAbsolutePath(), Long.valueOf(System.currentTimeMillis() - startTime)})); } }
ServletContext实现类为ApplicationContext。ApplicationFilterConfig负责Filter的实例化。FilterMap存储filter- mapping的配置。NamingResource存储web应用 的命名服务JNDI。
StandardContext的启动过程:
ContextConfig是Context的生命周期监听器
context的创建途径:
context的默认配置,优先使用conf目录下的,再次是conf/eng/host/目录下的,最后是context的configfile属性。
Before_start_event事件
在context启动之前触发,用于更新context的docBase属性和解决web目录锁的问题。 更新docBase是针对本身为war包的情况,修改docbase为解压后的文件目录 具体处理过程:
当antiResourceLocking属性为true时,tomcat会把web包或目录复制到临时文件目录。将context的docbase更新为临时目录下的web应用。
standardWrapper的start方法广播通知了它的状态变化,然后加载了所有启动时加载的servlet。
Tomcat通过Mapper维护请求链接与Host,context,wrapper等与contaioner的映射。同时通过MapperListener监听器监听所有的Host,context,wrapper组件,在相关组件启动、停止时注册或移除相关映射。
Connector接收到请求后,首先读取请求数据,然后调用CoyoteAdapter.service()完成请求处理。
根据connector的请求和响应对象创建Servlet请求,转换请求参数并完成映射, 请求URI解码,初始化请求的路径参数,检查URI是否合法,请求映射
原文链接:https://blog.csdn.net/ljz2016/article/details/84579671