mvn deploy
本章承接distributionManagement的配置讲解,专门解析
mvn deploy命令的执行机制。入门教程已覆盖mvn install(本地安装),本章解决"远程部署"与"本地安装"的本质差异,以及SNAPSHOT版本在团队协作中的特殊行为。
核心机制
mvn deploy是Maven生命周期中deploy阶段的触发命令。它的核心职责是:将当前项目的构建产物(主jar、pom、源码包、文档包等)从本地推送到远程仓库,使团队其他成员或下游系统能够通过坐标引用这些构件。
deploy与install的本质区别
| 维度 | mvn install | mvn deploy |
|---|---|---|
| 目标仓库 | 本地仓库(~/.m2/repository) | 远程仓库(由distributionManagement指定) |
| 生命周期阶段 | install | deploy |
| 前置阶段 | 自动执行validate到package的所有阶段 | 自动执行validate到install的所有阶段 |
| 可访问范围 | 仅本机用户 | 整个团队或公网用户 |
| 构件持久性 | 本地可随意删除 | 由私服管理,Release不可覆盖 |
| 认证要求 | 无需认证 | 需要settings.xml中server认证 |
关键洞察:deploy不是install的"升级版",而是install的"延伸版"。执行deploy时,Maven会先完成install的全部工作(编译、测试、打包、安装到本地),然后再额外执行上传远程的操作。install是deploy的必要前置,而非可选项。
deploy生命周期流程
deploy阶段绑定的是maven-deploy-plugin:deploy目标。完整的执行链如下:
- validate → 验证pom.xml结构
- compile → 编译主代码
- test-compile → 编译测试代码
- test → 运行单元测试
- package → 打包成jar/war
- verify → 运行集成测试和检查
- install → 安装到本地仓库
- deploy → 上传到远程仓库(distributionManagement指定)
SNAPSHOT部署的特殊行为
SNAPSHOT版本(如1.2.0-SNAPSHOT)在deploy时有三个特殊规则:
- 时间戳命名:上传后,私服会自动在文件名中加入时间戳和构建号,如
order-service-1.2.0-20240115.083022-1.jar。本地Maven解析SNAPSHOT依赖时,会下载最新的时间戳版本。 - 允许覆盖:同一SNAPSHOT可以反复deploy,每次都会生成新的时间戳文件,旧文件保留(可配置清理策略)。
- metadata.xml更新:私服会自动更新
maven-metadata.xml,记录最新版本的时间戳,供客户端判断是否需要重新下载。
生活类比:图书馆系统
想象Maven仓库是一所大学图书馆:
- mvn install:你把写好的论文复印一份,放进自己宿舍的书架(本地仓库)。只有你自己能看,室友来借也没有。
- mvn deploy:你把论文正式提交到图书馆(远程仓库),编入索引系统。全校师生都能通过索书号(GAV坐标)借阅,而且图书馆会永久保存。
- SNAPSHOT:你提交的是"草稿版"(Snapshot)。图书馆允许你每周更新草稿,每次更新都会在封面上贴新的日期标签(时间戳)。借阅者每次来借,都能拿到最新的一版草稿。
- RELEASE:你提交的是"定稿版"(Release)。图书馆规定定稿一旦上架,永远不可修改。如果有人引用你的结论,十年后他再来借,内容完全一致——这就是可复现性。
图示
deploy生命周期流程图
上图展示了mvn deploy的完整生命周期。install阶段(黄色)是deploy的必经之路——构件必须先进入本地仓库,才能被deploy插件读取并上传。deploy阶段本身(绿色)根据version类型分叉:SNAPSHOT走时间戳命名路径,Release保持原始版本号。
deploy前后仓库状态对比
上图对比了deploy执行前后的仓库状态。install只影响本地仓库,deploy在install的基础上把同样的内容复制到远程仓库。注意远程仓库会额外生成maven-metadata.xml,这是私服用于版本索引和SNAPSHOT解析的关键文件。
完整示例
场景
飞翔科技的order-service进入1.2.0版本迭代。CTO大翔要求:
- 小崔每天下班前deploy当天的SNAPSHOT,黄俪第二天联调时自动拿到最新版
- 白歌在版本稳定后deploy RELEASE,李眉部署到生产环境时引用固定版本
- 所有deploy操作必须经过单元测试(test阶段不能跳过)
小崔的SNAPSHOT日常部署
# 小崔完成功能开发,当前pom.xml版本为 1.2.0-SNAPSHOT
cd order-service
# 执行完整deploy(包含测试)
mvn clean deploy
# 控制台输出关键片段:
# [INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ order-service ---
# [INFO] Uploading to feixiang-snapshots: https://nexus.feixiang.com/...
# [INFO] Uploaded: order-service-1.2.0-20240115.083022-1.jar (45 kB)
# [INFO] Uploaded: order-service-1.2.0-20240115.083022-1.pom (3 kB)
# [INFO] Uploading: maven-metadata.xml
黄俪(前端)的联调pom.xml:
<dependency>
<groupId>com.feixiang</groupId>
<artifactId>order-service</artifactId>
<version>1.2.0-SNAPSHOT</version>
</dependency>
黄俪执行mvn compile时,Maven会检查私服上的maven-metadata.xml,自动下载1.2.0-SNAPSHOT的最新时间戳版本。如果小崔昨晚又deploy了一次,黄俪今天会拿到-2版本。
白歌的RELEASE正式发布
# 1. 移除SNAPSHOT后缀
mvn versions:set -DnewVersion=1.2.0
# 2. 确认所有测试通过
mvn clean test
# 3. 部署到发布仓库
mvn clean deploy
# 控制台输出关键片段:
# [INFO] --- maven-deploy-plugin:2.8.2:deploy (default-deploy) @ order-service ---
# [INFO] Uploading to feixiang-releases: https://nexus.feixiang.com/...
# [INFO] Uploaded: order-service-1.2.0.jar (45 kB)
# [INFO] Uploaded: order-service-1.2.0.pom (3 kB)
李眉(运维)的生产引用:
<dependency>
<groupId>com.feixiang</groupId>
<artifactId>order-service</artifactId>
<version>1.2.0</version> <!-- 固定版本,永不变动 -->
</dependency>
易错点与常见问题
误区一:deploy可以跳过install
错误认知:"我只想把jar传到远程,本地仓库不需要留一份,所以能不能只执行deploy不执行install?"
纠正:不能。deploy阶段在生命周期中位于install之后,执行deploy必然先执行install。即使你显式指定mvn deploy -DskipTests,install阶段仍然会发生。这是设计上的强制顺序——deploy插件从本地仓库读取构件上传,而非从target目录直接读取。
反例:
# 试图跳过install,直接deploy
mvn deploy -Dskip.install=true
# 结果:Maven不认识skip.install参数,install照常执行
如果你确实不想污染本地仓库(比如在CI环境中),可以在deploy后清理,或者使用-Dmaven.repo.local=/tmp/empty-repo指定一个临时本地仓库。
误区二:SNAPSHOT deploy后本地缓存不刷新
错误认知:"小崔deploy了新的SNAPSHOT,但我(黄俪)执行mvn compile还是拿到昨天的版本。"
纠正:Maven默认每天只检查一次SNAPSHOT更新。如果你今天已经编译过,Maven会把SNAPSHOT缓存到本地,直到第二天才重新检查远程。强制刷新需要:
# 方式一:强制更新所有SNAPSHOT
mvn compile -U
# -U = --update-snapshots
# 方式二:强制更新特定依赖
mvn dependency:purge-local-repository -DactTransitively=false \
-DmanualInclude=com.feixiang:order-service
反例:黄俪的pom.xml里写了1.2.0-SNAPSHOT,但她连续三天没有加-U,一直用着三天前的jar包,联调时反复出现"小崔说已经修了但黄俪还是报错"的诡异现象。
误区三:RELEASE版本重复deploy
错误认知:"1.2.0有个小bug,我改完代码重新deploy一下,覆盖掉之前的。"
纠正:Release仓库默认禁止覆盖。Nexus/Artifactory等私服对Release仓库有"deploy once"策略,防止已发布的固定版本被篡改。如果你尝试重新deploy 1.2.0:
Return code is: 400, ReasonPhrase: Bad Request
Repository does not allow updating assets: maven-releases
正确做法:
- 如果是紧急修复,升级版本号重新deploy(如
1.2.1) - 如果确实需要覆盖(不推荐),在Nexus管理界面临时开启"Allow redeploy",但会破坏下游的可复现性
小结
mvn deploy是Maven生命周期中最后一个阶段,它在mvn install的基础上,将构件推送到远程仓库供团队共享。核心要点:
- deploy包含install,不是替代关系
- SNAPSHOT部署生成时间戳,支持反复覆盖,适合持续集成
- RELEASE部署不可覆盖,保证构建可复现性
- SNAPSHOT消费端需要
-U参数强制刷新,否则可能拿到过期缓存
理解deploy与install的分工,以及SNAPSHOT的特殊治理规则,是团队协作中构件分发的基本功。
本章与全局的关系:本章讲解了deploy命令的执行机制。下一章将深入settings.xml的servers认证配置,解决"远程仓库凭什么让你上传"的权限问题。