Tomcat war包部署

简介:

开篇

 这篇文章主要针对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);
    }
}
目录
相关文章
|
3月前
|
Arthas 监控 Java
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
Arthas 可以用于监控和诊断在 Windows 系统下部署的 Tomcat 服务
163 2
|
2月前
|
JavaScript Java 应用服务中间件
centos部署vue项目(java,tomcat环境的搭建)
centos部署vue项目(java,tomcat环境的搭建)
37 0
|
4月前
|
XML Java 应用服务中间件
tomcat三种部署方式和推荐方式
tomcat三种部署方式和推荐方式
|
1天前
|
Web App开发 Java 应用服务中间件
【Java Web】在 IDEA 中部署 Tomcat
【Java Web】在 IDEA 中部署 Tomcat
7 0
|
4月前
|
Java 应用服务中间件
SpringBoot 项目war包部署 配置外置tomcat方法
SpringBoot 项目war包部署 配置外置tomcat方法
67 0
|
4天前
|
Java 应用服务中间件 Linux
阿里云服务器部署多个tomcat
阿里云服务器部署多个tomcat
|
1月前
|
Java 应用服务中间件
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
解决tomcat启动报错:无法在web.xml或使用此应用程序部署的jar文件中解析绝对的url [http:java.sun.com/jsp/jstl/core]
95 1
|
3月前
|
安全 Java 应用服务中间件
本地部署Tomcat开源服务器并结合内网穿透远程访问
本地部署Tomcat开源服务器并结合内网穿透远程访问
37 0
|
3月前
|
Java 应用服务中间件 Maven
Tomcat部署SpringBoot war包
Tomcat部署SpringBoot war包
28 0
|
3月前
|
Java 应用服务中间件 Linux
TomCat安装及快速部署
TomCat安装及快速部署
34 0