私服deploy失败最常见原因是distributionmanagement中repository url拼写错误,如缺少/repo/maven-releases/后缀或协议误用http而非https,maven报认证失败或405实为url错误。

私服地址写错导致 deploy 一直失败
最常见的情况是 distributionManagement 里 repository 或 snapshots/repository 的 url 拼错了,比如少个 /repository/maven-releases/ 后缀,或者协议写成 http 而不是私服要求的 https。Maven 不会明确告诉你“URL 不存在”,而是报一堆认证失败或 405 错误,让人误以为是权限问题。
实操建议:
- 先用
curl -I <url></url>检查 URL 是否可访问(注意:有些私服会拦截非浏览器请求,但至少能确认 404 还是 401) -
url必须和 Nexus/Artifactory 界面里 “Copy Dependency Coordinates” 功能给出的发布路径严格一致 - 快照版和正式版必须分两个
repository块,且id不能重复——否则 Maven 会随机选一个,部署到错误仓库
settings.xml 里的 server 配置不匹配 pom.xml 的 id
Maven 只认 settings.xml 中 <server></server> 的 <id></id> 和 pom 里 <repository><id></id></repository> 完全相等才加载账号密码。大小写、空格、下划线差异都会导致认证失败,错误信息通常是 Failed to deploy artifacts: Could not transfer artifact ... Access denied。
实操建议:
- 打开
~/.m2/settings.xml,确认存在<server></server>块,且其<id></id>和 pom 中<repository><id></id></repository>一模一样 - 密码不要明文写在
settings.xml里,用mvn --encrypt-password加密后填入<password></password> - 如果私服启用了 LDAP 或 token 认证,
<username></username>可能不是邮箱,而是登录名;<password></password>可能是 personal access token,不是 Web 登录密码
没开 snapshot 开关却往快照库发正式版
正式版(version 不带 -SNAPSHOT)必须部署到 <repository></repository>,快照版(带 -SNAPSHOT)必须部署到 <snapshots></snapshots> 子节点。但很多人只配了 <repository></repository>,结果 mvn deploy 时 Maven 自动把快照版也往正式库推,直接被私服拒绝,报错类似 Repository 'releases' does not allow updating artifact。
实操建议:
- 检查 pom 中 version:含
-SNAPSHOT→ 必须配置<snapshots></snapshots>;不含 → 必须配置<repository></repository> - 两个
<id></id>可以相同,也可以不同,但<url></url>必须指向不同路径(例如/repository/maven-snapshots/vs/repository/maven-releases/) - Nexus 默认关闭快照覆盖,如果要覆盖同名快照,得进 UI 把对应仓库的 “Deployment Policy” 改成
Allow Redeploy
跳过 maven-deploy-plugin 默认行为导致 Jar 包没上传
有人为控制构建流程,在 pluginManagement 或 profile 里重写了 maven-deploy-plugin,却漏掉了 <goals><goal>deploy</goal></goals>,或者把 <phase></phase> 改成了 none。结果 mvn deploy 看似跑完,实际什么都没传上去,本地 target/ 下有 jar,私服上却空空如也。
实操建议:
- 执行
mvn help:effective-pom,搜索maven-deploy-plugin,确认它是否绑定在deploy生命周期且 goal 是deploy - 除非有强定制需求,否则别在 pom 里显式配置该插件——Maven 3.9+ 默认已内置正确绑定
- 如果用了多模块项目,确保只有父 pom 写
distributionManagement,子模块不要重复写,否则子模块会尝试用自己的id去找settings.xml里的 server
真正卡住人的,往往不是配置项本身,而是私服返回的错误信息和真实原因严重脱节。比如 401 实际是 url 写错,405 实际是用了 http 却该用 https,而 Nexus 日志默认不打详细拒绝原因。调的时候别只盯着 pom,先抓包看 mvn 实际请求了哪个 URL、带了什么头、返回了什么 body。










