问题现象
在一个 Maven 子模块项目中执行:
bash
mvn clean package -DskipTests
或在 IDEA 中执行 Maven clean 时,报错类似:
text
Non-resolvable parent POM for com.example:child-module:1.0-SNAPSHOT:
Could not find artifact com.example:parent-project:pom:1.0-SNAPSHOT
and 'parent.relativePath' points at wrong local POM
表面看是父 POM 找不到,实际通常有三类原因:
text
1. 当前只拉了子模块,没有拉父工程源码
2. Maven 没有使用正确的 settings.xml
3. 私服可访问,但 SNAPSHOT 仓库策略没有正确启用
本文记录的是第三类问题:私服能访问,metadata 也存在,但 Maven 仍然解析不到 SNAPSHOT 父 POM。
先判断不是源码缺失
子模块 pom.xml 中通常会声明父工程:
xml
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
如果本地没有父工程源码,Maven 会尝试从本地仓库或远程仓库下载:
text
com.example:parent-project:pom:1.0-SNAPSHOT
所以第一步要确认私服里是否真的有这个父 POM。
可以用类似命令检查:
bash
curl -I "http://your-nexus.example.com/repository/maven-public/com/example/parent-project/1.0-SNAPSHOT/maven-metadata.xml"
如果返回:
text
HTTP/1.1 200 OK
说明私服中存在这个 SNAPSHOT 元数据。
如果返回:
text
HTTP/1.1 404
说明私服里没有这个包,需要找项目维护者确认:
text
1. 父工程源码仓库在哪里
2. 正确的 Maven 私服地址是什么
3. 依赖是否发布到了其它仓库
为什么只配置 mirror 还不够
很多人会在 settings.xml 里只配置一个全局镜像:
xml
<mirrors>
<mirror>
<id>internal-nexus</id>
<name>internal-nexus</name>
<mirrorOf>*</mirrorOf>
<url>http://your-nexus.example.com/repository/maven-public/</url>
</mirror>
</mirrors>
这个配置可以把下载请求导向私服,但它不等于声明了一个启用 SNAPSHOT 的仓库。
如果项目本身没有声明 snapshot repository,而 Maven 默认中央仓库又不支持 SNAPSHOT,可能出现这种情况:
text
私服地址是对的
metadata 能访问
settings 也生效
但 Maven 仍然解析不到 1.0-SNAPSHOT 父 POM
最后解决问题的关键,就是在 settings.xml 里显式声明 repository,并启用:
xml
<snapshots>
<enabled>true</enabled>
</snapshots>
推荐 settings.xml 示例
以下是一个通用模板,请把私服地址替换成自己的内部 Maven 仓库地址。
xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<localRepository>${user.home}/.m2/repository</localRepository>
<mirrors>
<mirror>
<id>internal-nexus-mirror</id>
<name>internal-nexus-mirror</name>
<mirrorOf>*</mirrorOf>
<url>http://your-nexus.example.com/repository/maven-public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>internal-nexus</id>
<repositories>
<repository>
<id>internal-maven-public</id>
<name>internal-maven-public</name>
<url>http://your-nexus.example.com/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>internal-maven-public-plugins</id>
<name>internal-maven-public-plugins</name>
<url>http://your-nexus.example.com/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>internal-nexus</activeProfile>
</activeProfiles>
</settings>
验证 settings 是否生效
不要在有问题的项目目录里先验证,因为 Maven 会先解析项目 POM,可能直接被父 POM 错误挡住。
可以先切到用户目录:
bash
cd ~
mvn help:effective-settings
检查输出里是否包含:
text
internal-nexus
your-nexus.example.com
snapshots
localRepository
Windows PowerShell 中可以这样过滤:
powershell
mvn help:effective-settings | findstr /i "internal-nexus snapshots localRepository"
清理失败缓存
Maven 解析依赖失败后,可能会在本地仓库留下 .lastUpdated 失败缓存。
配置修好以后,建议先删除对应依赖目录:
bash
rm -rf ~/.m2/repository/com/example/parent-project
Windows PowerShell:
powershell
Remove-Item -Recurse -Force "$env:USERPROFILE\.m2\repository\com\example\parent-project" -ErrorAction SilentlyContinue
然后强制刷新:
bash
mvn -U clean package -DskipTests
-U 的作用是强制更新 SNAPSHOT 和失败缓存。
IDEA 中仍然失败怎么办
命令行成功,但 IDEA 中 Maven clean 仍然失败时,通常是 IDEA 使用了另一套 Maven 配置。
检查:
text
Settings -> Build Tools -> Maven
重点确认:
text
Maven home path
User settings file
Local repository
JDK for importer
建议 IDEA 和命令行使用同一个:
text
settings.xml
localRepository
JDK
修改后执行:
text
Reload All Maven Projects
必要时重启 IDEA。
PowerShell 里的 curl 注意事项
在 Windows PowerShell 中,curl 可能是 Invoke-WebRequest 的别名,不是真正的 curl。
如果要使用 curl 参数,例如 -I,建议写:
powershell
curl.exe -I "http://your-nexus.example.com/repository/maven-public/..."
不要直接写:
powershell
curl -I "http://your-nexus.example.com/repository/maven-public/..."
否则可能会被 PowerShell 当成 Invoke-WebRequest,导致参数解析异常。
总结
这次问题最后解决的不是"换 Maven 安装目录",也不是"重新 clean",而是:
text
在 Maven settings.xml 中显式配置内部仓库 profile,
并启用 snapshots 下载策略。
核心配置是:
xml
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
当父工程或内部依赖版本是 1.0-SNAPSHOT 这类 SNAPSHOT 版本时,只配置 mirror 可能不够。
需要同时确认:
text
1. 私服中确实存在该 SNAPSHOT 依赖
2. settings.xml 被 Maven 正确读取
3. repository 启用了 snapshots
4. 本地失败缓存已清理
5. IDEA 使用的 Maven 配置与命令行一致