Tomcat Web目录部署

简介:

开篇

 这篇文章主要针对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);
    }
}
目录
相关文章
|
15天前
|
应用服务中间件 网络安全 nginx
快速上手!使用Docker和Nginx部署Web服务的完美指南
快速上手!使用Docker和Nginx部署Web服务的完美指南
|
15天前
|
XML Java 应用服务中间件
Tomcat_servlet部署、编译、配置、打包
Tomcat_servlet部署、编译、配置、打包
19 0
|
3天前
|
应用服务中间件 nginx
如何在树莓派部署Nginx并实现无公网ip远程访问内网制作的web网站
如何在树莓派部署Nginx并实现无公网ip远程访问内网制作的web网站
7 0
|
4天前
|
开发框架 JavaScript 安全
WIndows Server 2016 部署 Web服务(简单篇)
WIndows Server 2016 部署 Web服务(简单篇)
|
10天前
|
存储 Java 应用服务中间件
Springboot项目打war包部署到外置tomcat容器【详解版】
该文介绍了将Spring Boot应用改为war包并在外部Tomcat中部署的步骤:1) 修改pom.xml打包方式为war;2) 排除内置Tomcat依赖;3) 创建`ServletInitializer`类继承`SpringBootServletInitializer`;4) build部分需指定`finalName`;5) 使用`mvn clean package`打包,将war包放入外部Tomcat的webapps目录,通过startup脚本启动Tomcat并访问应用。注意,应用访问路径和静态资源引用需包含war包名。
|
11天前
|
存储 Java Unix
tomcat结构目录有哪些?
这些是Tomcat目录结构的主要部分,具体的目录结构可能会因Tomcat版本和配置而有所不同。这些目录和文件在Tomcat服务器的正常运行和Web应用程序的部署中起着关键作用。
5 0
|
16天前
|
测试技术 Linux Docker
【好玩的经典游戏】Docker部署FC-web游戏模拟器
【好玩的经典游戏】Docker部署FC-web游戏模拟器
53 1
|
22天前
|
Java 应用服务中间件 Linux
在阿里云服务器上部署Tomcat详细图文详解
本文介绍了在阿里云服务器上安装和配置JDK和Tomcat的步骤。首先,需要注册阿里云账号并进行实名认证,然后购买并设置服务器。接着,通过File Zilla连接服务器,创建Java和Tomcat的安装目录,并将JDK和Tomcat的tar.gz文件上传到服务器,解压并重命名。之后,配置JDK的环境变量,将catalina.sh复制到/etc/init.d/目录下,并修改相关配置。最后,启动Tomcat并配置安全组规则,确保可以通过公网访问。
|
25天前
|
Web App开发 Java 应用服务中间件
【Java Web】在 IDEA 中部署 Tomcat
【Java Web】在 IDEA 中部署 Tomcat
|
11月前
|
负载均衡 Java 应用服务中间件
部署Tomcat及其负载均衡
部署Tomcat及其负载均衡