Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計(jì)
這段代碼展示了 Apache Tomcat Maven Plugin(如 tomcat8-maven-plugin)中“部署”和“卸載”類目標(biāo)的完整設(shè)計(jì)體系。它通過(guò)多層抽象 + 組合復(fù)用 + 注解驅(qū)動(dòng)的方式,實(shí)現(xiàn)了高度靈活、可配置、可擴(kuò)展的遠(yuǎn)程 Tomcat 操作能力。
我們來(lái)逐層拆解理解:
?? 整體結(jié)構(gòu)概覽
AbstractWarCatalinaMojo ↓ AbstractDeployMojo ← 定義部署邏輯(war / context / both) ↓ AbstractDeployWarMojo ← 專用于 WAR 文件部署 ↓ DeployMojo ← @Mojo(name = "deploy") —— 綁定到 package 階段 DeployOnlyMojo ← @Mojo(name = "deploy-only") —— 不綁定生命周期 ↓ RedeployMojo ← 覆蓋 isUpdate() → true(自動(dòng) undeploy 再 deploy) RedeployOnlyMojo ← 同上,但不綁定生命周期 UndeployMojo ← 獨(dú)立實(shí)現(xiàn),用于卸載應(yīng)用
? 所有目標(biāo)都繼承自
AbstractWarCatalinaMojo,因此天然支持:
- 只處理 WAR 項(xiàng)目
- 連接遠(yuǎn)程 Tomcat Manager
- 多種認(rèn)證方式
- 日志與錯(cuò)誤處理
?? 核心類詳解
1??AbstractDeployMojo——部署策略的抽象基類
- 核心功能:根據(jù)
mode參數(shù)決定部署方式:war:只部署 WAR 文件(默認(rèn))context:只部署context.xmlboth:同時(shí)部署 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() );
}關(guān)鍵方法:
protected abstract File getWarFile(); // 子類提供 WAR 路徑 protected abstract void validateWarFile(); // 子類校驗(yàn) WAR 是否存在
- 參數(shù):
mode:部署模式contextFile:上下文文件路徑(默認(rèn)${project.build.directory}/.../META-INF/context.xml)update:是否先 undeploy 再 deploy(對(duì)應(yīng) Tomcat 的?update=true)tag:用于標(biāo)記部署版本(高級(jí)功能)
?? 它不關(guān)心 WAR 是文件還是目錄,把具體實(shí)現(xiàn)留給子類。
2??AbstractDeployWarMojo——WAR 文件部署的具體實(shí)現(xiàn)
覆蓋父類方法:
@Override
protected File getWarFile() {
return warFile; // 來(lái)自參數(shù),默認(rèn)是 target/${artifactId}.war
}
@Override
protected void validateWarFile() {
if (!warFile.exists()) throw ...;
}- 優(yōu)化
deployWar(): - 調(diào)用
getManager().deploy(..., warFile, ..., warFile.length())
顯式傳入文件大小 → 支持更高效的 HTTP 上傳(避免先讀入內(nèi)存)
/**
* {@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() );
}? 這是 最常用 的部署方式:直接上傳一個(gè)
.war文件到 Tomcat。
3??DeployMojovsDeployOnlyMojo——生命周期綁定差異
| 類 | 注解 | 行為 |
|---|---|---|
DeployMojo | @Execute(phase = LifecyclePhase.PACKAGE) | 執(zhí)行前自動(dòng)觸發(fā) package 階段(確保 WAR 已生成) |
DeployOnlyMojo | 無(wú) @Execute | 不觸發(fā)任何生命周期,假定 WAR 已存在 |
使用場(chǎng)景:
# 自動(dòng)打包并部署 mvn tomcat8:deploy # 假設(shè) WAR 已存在,直接部署(CI/CD 中常用) mvn tomcat8:deploy-only
??
@Execute是 Maven 插件的“前置任務(wù)”機(jī)制。
4??RedeployMojo/RedeployOnlyMojo——便捷別名
核心 trick:重寫 isUpdate() 返回 true
@Override
protected boolean isUpdate() {
return true; // 等價(jià)于 -Dmaven.tomcat.update=true
}
效果:Tomcat 會(huì)先 undeploy 同 path 的應(yīng)用,再 deploy 新的 → 避免“already exists”錯(cuò)誤
? 用戶無(wú)需記參數(shù),直接用
redeploy更直觀。
5??UndeployMojo——獨(dú)立卸載邏輯
簡(jiǎn)單直接:調(diào)用 manager.undeploy(path)
容錯(cuò)設(shè)計(jì):
if (failOnError) throw exception;
else log.warn("Failed to undeploy, but continuing...");
適用場(chǎng)景:清理環(huán)境、滾動(dòng)部署前移除舊版本
?? 設(shè)計(jì)亮點(diǎn)總結(jié)
| 特性 | 說(shuō)明 |
|---|---|
| 分層抽象 | 從“是否 WAR 項(xiàng)目” → “如何連接 Tomcat” → “部署什么” → “如何部署”,職責(zé)清晰 |
| 策略模式 | mode=war/context/both 允許不同部署策略 |
| 模板方法 | invokeManager() 調(diào)用子類實(shí)現(xiàn)的 deployXxx() |
| 生命周期集成 | @Execute(phase = PACKAGE) 自動(dòng)構(gòu)建 WAR |
| 用戶友好 | 提供 deploy / redeploy / deploy-only 等語(yǔ)義化目標(biāo) |
| 安全容錯(cuò) | failOnError 控制卸載失敗是否中斷構(gòu)建 |
??? 實(shí)際使用示例
場(chǎng)景 1:標(biāo)準(zhǔn)部署(自動(dòng)打包)
mvn tomcat8:deploy \ -Dtomcat.username=admin \ -Dtomcat.password=secret \ -Dmaven.tomcat.url=http://prod-server:8080/manager/text
場(chǎng)景 2:重新部署(覆蓋已有應(yīng)用)
mvn tomcat8:redeploy # 等價(jià)于 mvn tomcat8:deploy -Dmaven.tomcat.update=true
場(chǎng)景 3:僅卸載(不中斷構(gòu)建)
mvn tomcat8:undeploy -Dmaven.tomcat.failOnError=false
? 總結(jié)一句話
這套代碼通過(guò)“抽象基類 + 具體實(shí)現(xiàn) + 注解元數(shù)據(jù)”的組合,將 Tomcat 部署/卸載操作封裝成一組語(yǔ)義清晰、配置靈活、安全可靠的 Maven 目標(biāo)(goals),既滿足日常開發(fā)需求,也適配自動(dòng)化部署場(chǎng)景。
它是 Maven 插件設(shè)計(jì)的最佳實(shí)踐范例:高內(nèi)聚、低耦合、易擴(kuò)展、用戶友好。
到此這篇關(guān)于Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計(jì)的文章就介紹到這了,更多相關(guān)Tomcat Maven插件部署與卸載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Windows下的Tomcat7安裝與環(huán)境配置教程
Tomcat安裝配置教程,涵蓋JDK安裝、Tomcat下載與解壓、環(huán)境變量配置及啟動(dòng)驗(yàn)證,助您快速搭建開發(fā)環(huán)境2026-05-05
Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計(jì)
文章詳細(xì)介紹了Apache Tomcat Maven Plugin中的部署和卸載功能,通過(guò)多層抽象、組合復(fù)用和注解驅(qū)動(dòng)的設(shè)計(jì),實(shí)現(xiàn)了靈活、可配置的遠(yuǎn)程Tomcat操作,通過(guò)代碼展示了Apache Tomcat Maven Plugin(如 tomcat8-maven-plugin)中部署和卸載類目標(biāo)的設(shè)計(jì)體系,感興趣的朋友一起看看吧2026-02-02
Tomcat打破雙親委派機(jī)制實(shí)現(xiàn)隔離Web應(yīng)用的方法
本文主要介紹了Tomcat打破雙親委派機(jī)制實(shí)現(xiàn)隔離Web應(yīng)用的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
關(guān)于Keytool配置?Tomcat的HTTPS雙向認(rèn)證的問題
Keytool是一個(gè)Java數(shù)據(jù)證書的管理工具,?Keytool將密鑰(key)和證書(certificates)存在一個(gè)稱為keystore的文件中,這篇文章主要介紹了Keytool配置?Tomcat的HTTPS雙向認(rèn)證問題,需要的朋友可以參考下2022-06-06
一文搞懂如何部署啟動(dòng)多個(gè)tomcat并移植項(xiàng)目
本文給大家介紹部署啟動(dòng)多個(gè)tomcat并移植項(xiàng)目的操作方法,本文給大家介紹的非常詳細(xì),包括修改配置文件的方法也給大家列舉出來(lái)了,具體內(nèi)容詳情跟隨小編一起看看吧2021-06-06
idea配置Tomcat Deployment添加時(shí)沒有Artifact的問題及解決
這篇文章主要介紹了idea配置Tomcat Deployment添加時(shí)沒有Artifact的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
詳解從源碼分析tomcat如何調(diào)用Servlet的初始化
這篇文章主要介紹了詳解從源碼分析tomcat如何調(diào)用Servlet的初始化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04

