本文共 7799 字,大约阅读时间需要 25 分钟。
这篇文章主要针对Tomcat针对War包部署进行一些常用的逻辑判断,这部分的核心逻辑主要回答了以下几个问题(这部分其实说实话我也不是特别明白)。
1、Context对象的创建。
2、配置变更重新部署的前置处理。3、核心逻辑在于Context启动过程,但是这部分后面由单独的文章进行说明。2、针对每个war包,按照如下逻辑进行判断创建StandardContext对象:
public class HostConfig implements LifecycleListener { protected void deployWAR(ContextName cn, File war) { // 在War包的同名目录下的META-INF/context.xml文件 File xml = new File(host.getAppBaseFile(), cn.getBaseName() + "/" + Constants.ApplicationContextXml); File warTracker = new File(host.getAppBaseFile(), cn.getBaseName() + Constants.WarTracker); boolean xmlInWar = false; try (JarFile jar = new JarFile(war)) { JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml); if (entry != null) { xmlInWar = true; } } catch (IOException e) { } // 判断在War包的同名目录下存在META-INF/context.xml文件 boolean useXml = false; if (xml.exists() && unpackWARs && (!warTracker.exists() || warTracker.lastModified() == war.lastModified())) { useXml = true; } Context context = null; boolean deployThisXML = isDeployThisXML(war, cn); // 按照如下逻辑进行判断创建StandardContext对象 try { // 使用War包的同名目录下存在META-INF/context.xml文件创建StandardContext对象 if (deployThisXML && useXml && !copyXML) { synchronized (digesterLock) { try { context = (Context) digester.parse(xml); } catch (Exception e) { } finally { digester.reset(); if (context == null) { context = new FailedContext(); } } } context.setConfigFile(xml.toURI().toURL()); } else if (deployThisXML && xmlInWar) { // // 使用War包内的META-INF/context.xml文件创建StandardContext对象 synchronized (digesterLock) { try (JarFile jar = new JarFile(war)) { JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml); try (InputStream istream = jar.getInputStream(entry)) { context = (Context) digester.parse(istream); } } catch (Exception e) { } finally { digester.reset(); if (context == null) { context = new FailedContext(); } context.setConfigFile( UriUtil.buildJarUrl(war, Constants.ApplicationContextXml)); } } } else if (!deployThisXML && xmlInWar) { } else { // 使用contextClass属性指定的类型创建Context对象, // 不指定则用org.apache.catalina.core.StandardContext来进行创建。 context = (Context) Class.forName(contextClass).getConstructor().newInstance(); } } catch (Throwable t) { } finally { if (context == null) { context = new FailedContext(); } } boolean copyThisXml = false; if (deployThisXML) { if (host instanceof StandardHost) { copyThisXml = ((StandardHost) host).isCopyXML(); } if (!copyThisXml && context instanceof StandardContext) { copyThisXml = ((StandardContext) context).getCopyXML(); } if (xmlInWar && copyThisXml) { // Change location of XML file to config base xml = new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml"); try (JarFile jar = new JarFile(war)) { JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml); try (InputStream istream = jar.getInputStream(entry); FileOutputStream fos = new FileOutputStream(xml); BufferedOutputStream ostream = new BufferedOutputStream(fos, 1024)) { byte buffer[] = new byte[1024]; while (true) { int n = istream.read(buffer); if (n < 0) { break; } ostream.write(buffer, 0, n); } ostream.flush(); } } catch (IOException e) { /* Ignore */ } } } DeployedApplication deployedApp = new DeployedApplication(cn.getName(), xml.exists() && deployThisXML && copyThisXml); try { deployedApp.redeployResources.put (war.getAbsolutePath(), Long.valueOf(war.lastModified())); if (deployThisXML && xml.exists() && copyThisXml) { deployedApp.redeployResources.put(xml.getAbsolutePath(), Long.valueOf(xml.lastModified())); } else { // In case an XML file is added to the config base later deployedApp.redeployResources.put( (new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml")).getAbsolutePath(), Long.valueOf(0)); } // 通过Host的addChild()方法将Context实例添加到Host Class clazz = Class.forName(host.getConfigClass()); LifecycleListener listener = (LifecycleListener) clazz.getConstructor().newInstance(); context.addLifecycleListener(listener); context.setName(cn.getName()); context.setPath(cn.getPath()); context.setWebappVersion(cn.getVersion()); context.setDocBase(cn.getBaseName() + ".war"); // 添加Context对象到StandardHost对象当中, // 如果Host已启动那么同事启动Context对象。 host.addChild(context); } catch (Throwable t) { } finally { // 将Context描述文件、War包及web.xml等资源添加到守护资源, // 以便文件发生变更时重新部署及加载Web应用。 boolean unpackWAR = unpackWARs; if (unpackWAR && context instanceof StandardContext) { unpackWAR = ((StandardContext) context).getUnpackWAR(); } if (unpackWAR && context.getDocBase() != null) { File docBase = new File(host.getAppBaseFile(), cn.getBaseName()); deployedApp.redeployResources.put(docBase.getAbsolutePath(), Long.valueOf(docBase.lastModified())); addWatchedResources(deployedApp, docBase.getAbsolutePath(), context); if (deployThisXML && !copyThisXml && (xmlInWar || xml.exists())) { deployedApp.redeployResources.put(xml.getAbsolutePath(), Long.valueOf(xml.lastModified())); } } else { addWatchedResources(deployedApp, null, context); } addGlobalRedeployResources(deployedApp); } deployed.put(cn.getName(), deployedApp); }}
转载地址:http://dityx.baihongyu.com/