美文网首页Tomcat
Tomcat war包部署

Tomcat war包部署

作者: 晴天哥_王志 | 来源:发表于2018-11-10 17:38 被阅读50次

    开篇

    这篇文章主要针对Tomcat针对War包部署进行一些常用的逻辑判断,这部分的核心逻辑主要回答了以下几个问题(这部分其实说实话我也不是特别明白)。

    1、Context对象的创建。
    2、配置变更重新部署的前置处理。
    3、核心逻辑在于Context启动过程,但是这部分后面由单独的文章进行说明。

    部署过程

    • 1、对于Host的appBase目录下所有符合条件的war包,由线程池完成部署。

    • 2、针对每个war包,按照如下逻辑进行判断创建StandardContext对象

      • 条件判断一:如果Host的deployXML属性为True,且在War包的同名目录下存在META-INF/context.xml文件,同时Context的copyXML属性为false,则用该context.xml创建Context实例。

      • 条件判断二:如果Host的deployXML属性为True,且在War包压缩文件下存在META-INF/context.xml文件,则使用该文件创建Context对象。

      • 条件判断三:如果deployXML属性为true,且在War包压缩文件下存在META-INF/context.xml文件,则构造FailedContext对象。

      • 条件判断四:其他情况下以contextClass属性指定的类型创建Context对象,不指定则用org.apache.catalina.core.StandardContext来进行创建。

    • 3、为Context实例添加ContextConfig生命周期监听器。

    • 4、通过Host的addChild()方法将Context实例添加到Host。该方法会判断Host是否启动,如果已启动则直接启动Context对象。

    • 5、将Context描述文件、War包及web.xml等资源添加到守护资源,以便文件发生变更时重新部署及加载Web应用。

    源码解析

    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);
        }
    }
    

    相关文章

      网友评论

        本文标题:Tomcat war包部署

        本文链接:https://www.haomeiwen.com/subject/gpfhxqtx.html