Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計(jì)
這段代碼展示了 Apache Tomcat Maven Plugin(如 tomcat8-maven-plugin)中“部署”和“卸載”類目標(biāo)的完整設(shè)計(jì)體系。它通過多層抽象 + 組合復(fù)用 + 注解驅(qū)動的方式,實(shí)現(xiàn)了高度靈活、可配置、可擴(kuò)展的遠(yuǎn)程 Tomcat 操作能力。
我們來逐層拆解理解:
?? 整體結(jié)構(gòu)概覽
AbstractWarCatalinaMojo ↓ AbstractDeployMojo ← 定義部署邏輯(war / context / both) ↓ AbstractDeployWarMojo ← 專用于 WAR 文件部署 ↓ DeployMojo ← @Mojo(name = "deploy") —— 綁定到 package 階段 DeployOnlyMojo ← @Mojo(name = "deploy-only") —— 不綁定生命周期 ↓ RedeployMojo ← 覆蓋 isUpdate() → true(自動 undeploy 再 deploy) RedeployOnlyMojo ← 同上,但不綁定生命周期 UndeployMojo ← 獨(dú)立實(shí)現(xiàn),用于卸載應(yīng)用
? 所有目標(biāo)都繼承自
AbstractWarCatalinaMojo,因此天然支持:
- 只處理 WAR 項(xiàng)目
- 連接遠(yuǎn)程 Tomcat Manager
- 多種認(rèn)證方式
- 日志與錯誤處理
?? 核心類詳解
1??AbstractDeployMojo——部署策略的抽象基類
- 核心功能:根據(jù)
mode參數(shù)決定部署方式:war:只部署 WAR 文件(默認(rèn))context:只部署context.xmlboth:同時部署 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(對應(yīng) Tomcat 的?update=true)tag:用于標(biāo)記部署版本(高級功能)
?? 它不關(guān)心 WAR 是文件還是目錄,把具體實(shí)現(xiàn)留給子類。
2??AbstractDeployWarMojo——WAR 文件部署的具體實(shí)現(xiàn)
覆蓋父類方法:
@Override
protected File getWarFile() {
return warFile; // 來自參數(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() );
}? 這是 最常用 的部署方式:直接上傳一個
.war文件到 Tomcat。
3??DeployMojovsDeployOnlyMojo——生命周期綁定差異
| 類 | 注解 | 行為 |
|---|---|---|
DeployMojo | @Execute(phase = LifecyclePhase.PACKAGE) | 執(zhí)行前自動觸發(fā) package 階段(確保 WAR 已生成) |
DeployOnlyMojo | 無 @Execute | 不觸發(fā)任何生命周期,假定 WAR 已存在 |
使用場景:
# 自動打包并部署 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; // 等價于 -Dmaven.tomcat.update=true
}
效果:Tomcat 會先 undeploy 同 path 的應(yīng)用,再 deploy 新的 → 避免“already exists”錯誤
? 用戶無需記參數(shù),直接用
redeploy更直觀。
5??UndeployMojo——獨(dú)立卸載邏輯
簡單直接:調(diào)用 manager.undeploy(path)
容錯設(shè)計(jì):
if (failOnError) throw exception;
else log.warn("Failed to undeploy, but continuing...");
適用場景:清理環(huán)境、滾動部署前移除舊版本
?? 設(shè)計(jì)亮點(diǎn)總結(jié)
| 特性 | 說明 |
|---|---|
| 分層抽象 | 從“是否 WAR 項(xiàng)目” → “如何連接 Tomcat” → “部署什么” → “如何部署”,職責(zé)清晰 |
| 策略模式 | mode=war/context/both 允許不同部署策略 |
| 模板方法 | invokeManager() 調(diào)用子類實(shí)現(xiàn)的 deployXxx() |
| 生命周期集成 | @Execute(phase = PACKAGE) 自動構(gòu)建 WAR |
| 用戶友好 | 提供 deploy / redeploy / deploy-only 等語義化目標(biāo) |
| 安全容錯 | failOnError 控制卸載失敗是否中斷構(gòu)建 |
??? 實(shí)際使用示例
場景 1:標(biāo)準(zhǔn)部署(自動打包)
mvn tomcat8:deploy \ -Dtomcat.username=admin \ -Dtomcat.password=secret \ -Dmaven.tomcat.url=http://prod-server:8080/manager/text
場景 2:重新部署(覆蓋已有應(yīng)用)
mvn tomcat8:redeploy # 等價于 mvn tomcat8:deploy -Dmaven.tomcat.update=true
場景 3:僅卸載(不中斷構(gòu)建)
mvn tomcat8:undeploy -Dmaven.tomcat.failOnError=false
? 總結(jié)一句話
這套代碼通過“抽象基類 + 具體實(shí)現(xiàn) + 注解元數(shù)據(jù)”的組合,將 Tomcat 部署/卸載操作封裝成一組語義清晰、配置靈活、安全可靠的 Maven 目標(biāo)(goals),既滿足日常開發(fā)需求,也適配自動化部署場景。
它是 Maven 插件設(shè)計(jì)的最佳實(shí)踐范例:高內(nèi)聚、低耦合、易擴(kuò)展、用戶友好。
到此這篇關(guān)于Tomcat Maven插件部署與卸載的完整架構(gòu)設(shè)計(jì)的文章就介紹到這了,更多相關(guān)Tomcat Maven插件部署與卸載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
tomcat何時寫回響應(yīng)數(shù)據(jù)報的詳析
這篇文章主要給大家介紹了關(guān)于tomcat是何時寫回響應(yīng)數(shù)據(jù)報的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用tomcat具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
tomcat?websocket?WsFrameServer內(nèi)存溢出的問題解決
本文主要介紹了tomcat?websocket?WsFrameServer內(nèi)存溢出的問題解決,文中通過圖文示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12

