美文网首页WebTomcat
Tomcat Web目录部署

Tomcat Web目录部署

作者: 晴天哥_王志 | 来源:发表于2018-11-10 00:13 被阅读61次

    开篇

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

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

    部署过程

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

    • 2、针对每个目录,按照如下逻辑进行判断:

      • 条件判断一:如果Host的deployXML属性值为true,并且存在META-INF/context.xml文件,则由Digester解析content.xml文件创建Context对象。

      • 条件判断二:如果Host的deployXML属性值为false,但是存在META-INF/context.xml文件,则构造FailedContext对象。

      • 条件判断三:其他情况下根据Host的contextClass属性指定的类型创建Context对象,如不指定则为org.apache.catalina.core.StandardContext。

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

    • 4、通过Host的addChild()方法将Context实例对象添加到Host,该方法会判断Host是否启动,如果已启动则直接启动Context对象。Context的启动过程才是核心逻辑,后面会单独有文章进行说明

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

    源码解析

    public class HostConfig implements LifecycleListener {
    
        protected void deployDirectory(ContextName cn, File dir) {
    
            // step1、针对Web目录进行部署
            Context context = null;
            // ApplicationContextXml = "META-INF/context.xml"
            File xml = new File(dir, Constants.ApplicationContextXml);
            File xmlCopy =
                    new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml");
    
    
            DeployedApplication deployedApp;
            boolean copyThisXml = isCopyXML();
            boolean deployThisXML = isDeployThisXML(dir, cn);
    
            try {
                // 条件判断一:如果Host的deployXML属性值为true,
                // 并且存在META-INF/context.xml文件,
                // 则由Digester解析content.xml文件创建Context对象。
                if (deployThisXML && xml.exists()) {
                    synchronized (digesterLock) {
                        try {
                            context = (Context) digester.parse(xml);
                        } catch (Exception e) {
                            log.error(sm.getString(
                                    "hostConfig.deployDescriptor.error",
                                    xml), e);
                            context = new FailedContext();
                        } finally {
                            digester.reset();
                            if (context == null) {
                                context = new FailedContext();
                            }
                        }
                    }
    
                    if (copyThisXml == false && context instanceof StandardContext) {
                        // Host is using default value. Context may override it.
                        copyThisXml = ((StandardContext) context).getCopyXML();
                    }
    
                    if (copyThisXml) {
                        Files.copy(xml.toPath(), xmlCopy.toPath());
                        context.setConfigFile(xmlCopy.toURI().toURL());
                    } else {
                        context.setConfigFile(xml.toURI().toURL());
                    }
                // 条件判断二:如果Host的deployXML属性值为false,
                // 但是存在META-INF/context.xml文件,则构造FailedContext对象。
                } else if (!deployThisXML && xml.exists()) {
                    // Block deployment as META-INF/context.xml may contain security
                    // configuration necessary for a secure deployment.
                    log.error(sm.getString("hostConfig.deployDescriptor.blocked",
                            cn.getPath(), xml, xmlCopy));
                    context = new FailedContext();
                } else {
                    // 条件判断三:其他情况下根据Host的contextClass属性指定的类型创建Context对象,
                    // 如不指定则为org.apache.catalina.core.StandardContext。
                    context = (Context) Class.forName(contextClass).getConstructor().newInstance();
                }
    
                // step2、为Context实例添加ContextConfig生命周期监听器。
                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());
                // 通过Host的addChild()方法将Context实例对象添加到Host,
                // 该方法会判断Host是否启动,如果已启动则直接启动Context对象。
                host.addChild(context);
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("hostConfig.deployDir.error",
                        dir.getAbsolutePath()), t);
            } finally {
                // step3、将Context描述文件、Web应用目录及web.xml等添加到守护资源,
                // 以便文件发生变更时重新部署或者加载web应用。
                deployedApp = new DeployedApplication(cn.getName(),
                        xml.exists() && deployThisXML && copyThisXml);
                deployedApp.redeployResources.put(dir.getAbsolutePath() + ".war",
                        Long.valueOf(0));
                deployedApp.redeployResources.put(dir.getAbsolutePath(),
                        Long.valueOf(dir.lastModified()));
                if (deployThisXML && xml.exists()) {
                    if (copyThisXml) {
                        deployedApp.redeployResources.put(
                                xmlCopy.getAbsolutePath(),
                                Long.valueOf(xmlCopy.lastModified()));
                    } else {
                        deployedApp.redeployResources.put(
                                xml.getAbsolutePath(),
                                Long.valueOf(xml.lastModified()));
    
                        deployedApp.redeployResources.put(
                                xmlCopy.getAbsolutePath(),
                                Long.valueOf(0));
                    }
                } else {
                    deployedApp.redeployResources.put(
                            xmlCopy.getAbsolutePath(),
                            Long.valueOf(0));
                    if (!xml.exists()) {
                        deployedApp.redeployResources.put(
                                xml.getAbsolutePath(),
                                Long.valueOf(0));
                    }
                }
                addWatchedResources(deployedApp, dir.getAbsolutePath(), context);
                addGlobalRedeployResources(deployedApp);
            }
    
            deployed.put(cn.getName(), deployedApp);
        }
    }
    

    相关文章

      网友评论

        本文标题:Tomcat Web目录部署

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