当前位置: 代码网 > it编程>编程语言>Java > Tomcat Maven插件部署与卸载的完整架构设计

Tomcat Maven插件部署与卸载的完整架构设计

2026年02月10日 Java 我要评论
这段代码展示了 apache tomcat maven plugin(如 tomcat8-maven-plugin)中“部署”和“卸载”类目标的完整设计

这段代码展示了 apache tomcat maven plugin(如 tomcat8-maven-plugin)中“部署”和“卸载”类目标的完整设计体系。它通过多层抽象 + 组合复用 + 注解驱动的方式,实现了高度灵活、可配置、可扩展的远程 tomcat 操作能力。

我们来逐层拆解理解:

🌐 整体结构概览

abstractwarcatalinamojo
  ↓
abstractdeploymojo                 ← 定义部署逻辑(war / context / both)
  ↓
abstractdeploywarmojo              ← 专用于 war 文件部署
  ↓
deploymojo                         ← @mojo(name = "deploy") —— 绑定到 package 阶段
deployonlymojo                     ← @mojo(name = "deploy-only") —— 不绑定生命周期
  ↓
redeploymojo                       ← 覆盖 isupdate() → true(自动 undeploy 再 deploy)
redeployonlymojo                   ← 同上,但不绑定生命周期
undeploymojo                       ← 独立实现,用于卸载应用

✅ 所有目标都继承自 abstractwarcatalinamojo,因此天然支持:

  • 只处理 war 项目
  • 连接远程 tomcat manager
  • 多种认证方式
  • 日志与错误处理

🔍 核心类详解

1️⃣abstractdeploymojo——部署策略的抽象基类

  • 核心功能:根据 mode 参数决定部署方式:
    • war:只部署 war 文件(默认)
    • context:只部署 context.xml
    • both:同时部署 war + context.xml
@override
    public void invokemanager()
        throws mojoexecutionexception, tomcatmanagerexception, ioexception
    {
        if ( "war".equals( mode ) )
        {
            deploywar();
        }
        else if ( "context".equals( mode ) )
        {
            deploycontext();
        }
        else if ( "both".equals( mode ) )
        {
            deploywarandcontext();
        }
        else
        {
            throw new mojoexecutionexception( messagesprovider.getmessage( "abstractdeploymojo.unknownmode", mode ) );
        }
    }
	/**
     * deploys the war to tomcat.
     *
     * @throws org.apache.maven.plugin.mojoexecutionexception
     *                             if there was a problem locating the war
     * @throws org.apache.tomcat.maven.common.deployer.tomcatmanagerexception
     *                             if the tomcat manager request fails
     * @throws java.io.ioexception if an i/o error occurs
     */
    protected void deploywar()
        throws mojoexecutionexception, tomcatmanagerexception, ioexception
    {
        validatewarfile();
        getlog().info( messagesprovider.getmessage( "abstractdeploymojo.deployingwar", getdeployedurl() ) );
        url warurl = getwarfile().tourl();
        log( getmanager().deploy( getpath(), warurl, isupdate(), gettag() ).gethttpresponsebody() );
    }
    /**
     * deploys the context xml file to tomcat.
     *
     * @throws org.apache.maven.plugin.mojoexecutionexception
     *                             if there was a problem locating the context xml file
     * @throws org.apache.tomcat.maven.common.deployer.tomcatmanagerexception
     *                             if the tomcat manager request fails
     * @throws java.io.ioexception if an i/o error occurs
     */
    protected void deploycontext()
        throws mojoexecutionexception, tomcatmanagerexception, ioexception
    {
        validatecontextfile();
        getlog().info( messagesprovider.getmessage( "abstractdeploymojo.deployingcontext", getdeployedurl() ) );
        url contexturl = getcontextfile().tourl();
        log( getmanager().deploycontext( getpath(), contexturl, isupdate(), gettag() ).gethttpresponsebody() );
    }
    /**
     * deploys the war and context xml file to tomcat.
     *
     * @throws org.apache.maven.plugin.mojoexecutionexception
     *                             if there was a problem locating either the war or the context xml file
     * @throws org.apache.tomcat.maven.common.deployer.tomcatmanagerexception
     *                             if the tomcat manager request fails
     * @throws java.io.ioexception if an i/o error occurs
     */
    protected void deploywarandcontext()
        throws mojoexecutionexception, tomcatmanagerexception, ioexception
    {
        validatewarfile();
        validatecontextfile();
        getlog().info( messagesprovider.getmessage( "abstractdeploymojo.deployingwarcontext", getdeployedurl() ) );
        url warurl = getwarfile().tourl();
        url contexturl = getcontextfile().tourl();
        tomcatmanagerresponse tomcatresponse = getmanager().deploycontext( getpath(), contexturl, warurl, isupdate(), gettag() );
        checktomcatresponse( tomcatresponse );
        log( tomcatresponse.gethttpresponsebody() );
    }

关键方法

protected abstract file getwarfile();      // 子类提供 war 路径
protected abstract void validatewarfile(); // 子类校验 war 是否存在
  • 参数
    • mode:部署模式
    • contextfile:上下文文件路径(默认 ${project.build.directory}/.../meta-inf/context.xml
    • update:是否先 undeploy 再 deploy(对应 tomcat 的 ?update=true
    • tag:用于标记部署版本(高级功能)

💡 它不关心 war 是文件还是目录,把具体实现留给子类。

2️⃣abstractdeploywarmojo——war 文件部署的具体实现

覆盖父类方法

@override
protected file getwarfile() {
    return warfile; // 来自参数,默认是 target/${artifactid}.war
}
@override
protected void validatewarfile() {
    if (!warfile.exists()) throw ...;
}
  • 优化 deploywar()
  • 调用 getmanager().deploy(..., warfile, ..., warfile.length())

显式传入文件大小 → 支持更高效的 http 上传(避免先读入内存)

/**
     * {@inheritdoc}
     */
    @override
    protected void deploywar()
        throws mojoexecutionexception, tomcatmanagerexception, ioexception
    {
        validatewarfile();
        getlog().info( messagesprovider.getmessage( "abstractdeploymojo.deployingwar", getdeployedurl() ) );
        tomcatmanagerresponse tomcatmanagerresponse =
            getmanager().deploy( getpath(), warfile, isupdate(), gettag(), warfile.length() );
        checktomcatresponse( tomcatmanagerresponse );
        getlog().info( "tomcatmanager status code:" + tomcatmanagerresponse.getstatuscode() + ", reasonphrase:"
                           + tomcatmanagerresponse.getreasonphrase() );
        log( tomcatmanagerresponse.gethttpresponsebody() );
    }

✅ 这是 最常用 的部署方式:直接上传一个 .war 文件到 tomcat。

3️⃣deploymojovsdeployonlymojo——生命周期绑定差异

注解行为
deploymojo@execute(phase = lifecyclephase.package)执行前自动触发 package 阶段(确保 war 已生成)
deployonlymojo@execute不触发任何生命周期,假定 war 已存在

使用场景:

# 自动打包并部署
mvn tomcat8:deploy
# 假设 war 已存在,直接部署(ci/cd 中常用)
mvn tomcat8:deploy-only

🔹 @execute 是 maven 插件的“前置任务”机制。

4️⃣redeploymojo/redeployonlymojo——便捷别名

核心 trick:重写 isupdate() 返回 true

@override
protected boolean isupdate() {
    return true; // 等价于 -dmaven.tomcat.update=true
}

效果:tomcat 会先 undeploy 同 path 的应用,再 deploy 新的 → 避免“already exists”错误

✅ 用户无需记参数,直接用 redeploy 更直观。

5️⃣undeploymojo——独立卸载逻辑

简单直接:调用 manager.undeploy(path)

容错设计

if (failonerror) throw exception;
else log.warn("failed to undeploy, but continuing...");

适用场景:清理环境、滚动部署前移除旧版本

🧩 设计亮点总结

特性说明
分层抽象从“是否 war 项目” → “如何连接 tomcat” → “部署什么” → “如何部署”,职责清晰
策略模式mode=war/context/both 允许不同部署策略
模板方法invokemanager() 调用子类实现的 deployxxx()
生命周期集成@execute(phase = package) 自动构建 war
用户友好提供 deploy / redeploy / deploy-only 等语义化目标
安全容错failonerror 控制卸载失败是否中断构建

🛠️ 实际使用示例

场景 1:标准部署(自动打包)

mvn tomcat8:deploy \
  -dtomcat.username=admin \
  -dtomcat.password=secret \
  -dmaven.tomcat.url=http://prod-server:8080/manager/text

场景 2:重新部署(覆盖已有应用)

mvn tomcat8:redeploy
# 等价于 mvn tomcat8:deploy -dmaven.tomcat.update=true

场景 3:仅卸载(不中断构建)

mvn tomcat8:undeploy -dmaven.tomcat.failonerror=false

✅ 总结一句话

这套代码通过“抽象基类 + 具体实现 + 注解元数据”的组合,将 tomcat 部署/卸载操作封装成一组语义清晰、配置灵活、安全可靠的 maven 目标(goals),既满足日常开发需求,也适配自动化部署场景。

它是 maven 插件设计的最佳实践范例:高内聚、低耦合、易扩展、用户友好。

到此这篇关于tomcat maven插件部署与卸载的完整架构设计的文章就介绍到这了,更多相关tomcat maven插件部署与卸载内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com