Maven 发布部署与最佳实践
把构件从本地仓库送到"其他人能用"的位置,涉及 deploy 机制、release 流程与中央仓库规范。本节梳理从私有部署到公开中央仓库的完整发布路径。
mvn deploy:部署到远程仓库
deploy 阶段把构建产物与 POM 上传到 <distributionManagement> 配置的远程仓库:
xml
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>https://nexus.example.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>https://nexus.example.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>bash
mvn deploy发布规则
| 版本号 | 去向 | 特点 |
|---|---|---|
1.0.0(release) | <repository> | 同一版本不可重复部署 |
1.0.0-SNAPSHOT(snapshot) | <snapshotRepository> | 可重复覆盖,下游拉取总是最新快照 |
认证与权限
settings.xml 中配置与仓库 id 一致的 server 凭据:
xml
<servers>
<server>
<id>nexus-releases</id>
<username>deployer</username>
<password>encrypted-password</password>
</server>
</servers>deploy 与 install 的区别
| 命令 | 目标位置 | 场景 |
|---|---|---|
mvn install | 本地仓库 ~/.m2/repository | 本机模块间依赖 |
mvn deploy | 远程仓库(Nexus/Central) | 供团队/公众使用 |
release-plugin:规范化版本发布
手工改版本号容易出错,release-plugin 把"改版本 → 打 tag → 构建 → 发布 → 升版本"串成受控流程:
prepare:准备发布
bash
mvn release:prepare执行步骤:
1. 检查:工作区无未提交变更、版本号合法
2. 修改版本:去除 -SNAPSHOT(如 1.0.0-SNAPSHOT → 1.0.0)
3. 构建验证:mvn verify
4. 打 tag:按 tagNameFormat 在 Git 打标签
5. 升版本:版本号变为 1.0.1-SNAPSHOT
6. 提交:提交 POM 变更与 tagperform:执行发布
bash
mvn release:perform从 prepare 打的 tag 检出代码,全新构建并 deploy 到远程仓库,保证发布物与 tag 严格一致。
参数与配置
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<tagNameFormat>v@{project.version}</tagNameFormat>
<autoVersionSubmodules>true</autoVersionSubmodules>
<preparationGoals>clean verify</preparationGoals>
<arguments>-DskipTests</arguments>
</configuration>
</plugin>release 的替代方案
release-plugin 流程较重(需要本地写权限、修改 POM 提交)。现代 CI/CD 更常用轻量方案:
| 方案 | 思路 |
|---|---|
| ${revision} + CI | 版本号由 CI 注入,流水线直接 mvn deploy -Drevision=1.0.0 |
| Git tag 触发 | 打 tag 触发流水线,从 tag 构建发布 |
| semantic-release | JS 生态方案,Java 项目可参照其版本计算思路 |
中央仓库发布流程
发布到 Maven Central(repo.maven.apache.org)需要满足严格的规范:
1. 必要条件
- 拥有可解析的域名(
com.example等,不能用com.github.xxx的私有名) - 构件使用正式版本号(不能是
-SNAPSHOT) - 通过
central.sonatype.org的 OSSRH(Sonatype Open Source Software Repository Hosting)发布 - 提供 GPL/APL 等 LICENSE 文件
2. 基础 POM 要求
xml
<name>Project Name</name>
<description>Project Description</description>
<url>https://github.com/org/project</url>
<licenses>
<license>
<name>Apache License 2.0</name>
<url>https://www.apache.org/licenses/LICENSE-2.0</url>
</license>
</licenses>
<scm>
<connection>scm:git:https://github.com/org/project.git</connection>
<developerConnection>scm:git:https://github.com/org/project.git</developerConnection>
<url>https://github.com/org/project</url>
</scm>
<developers>
<developer>
<name>Developer Name</name>
<email>dev@example.com</email>
</developer>
</developers>3. 源码与 javadoc
发布到 Central 需要同时提供 -sources.jar 与 -javadoc.jar:
xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals><goal>jar-no-fork</goal></goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadoc</id>
<goals><goal>jar</goal></goals>
</execution>
</executions>
</plugin>4. 签名(GPG)
所有发布物需用 GPG 签名:
bash
mvn clean deploy -P release -Dgpg.passphrase=xxxxml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals><goal>sign</goal></goals>
</execution>
</executions>
</plugin>5. 发布与同步
bash
# 部署到 OSSRH staging 仓库
mvn clean deploy
# 在 oss.sonatype.org 中:
# 1. 关闭 staging 仓库并验证内容
# 2. 确认无误后 release,自动同步到中央仓库(几分钟后生效)发布最佳实践
- 发布物可复现:用
${revision}+ tag 绑定版本,保证同一 tag 产物一致 - 发布前全量验证:
mvn verify跑完单测与集成测试再 deploy - 版本号规范化:遵循语义化版本(major.minor.patch),破坏性变更升 major
- 发布权限收敛:deploy 账号独立,凭据加密,不在 POM 里写明文密码
- 日志留痕:记录每次发布的版本、tag、构建号,便于回溯
- Central 发布用 staging:先在 staging 仓库自检,避免直接污染正式仓库
常见问题
- deploy 401/403? server id 与仓库 id 不匹配、凭据错误或权限不足。
- snapshot 能发布到 releases 仓库吗? 不能,Nexus 对 releases 仓库默认拒绝 snapshot;反之亦然(策略可配)。
- Central 拒绝发布? 检查 LICENSE、SCM、sources/javadoc、GPG 签名是否齐全,或版本号重复。
- release:perform 失败? 多因 tag 已存在、远端无写权限、或 prepare 阶段 POM 有未提交变更。