Maven Resolver始终从远程仓库下载maven-metadata.xml问题排查
Maven依赖加载器快照依赖解析问题
项目代码
Java核心实现
public class ResolverTest { private static final File LOCAL_REPO_DIR = new File("localRepo"); public static void main(String[] args) throws MalformedURLException, DependencyResolutionException { downloadLibraries( Arrays.asList( "https://repo1.maven.org/maven2/", "https://repository.apache.org/content/repositories/snapshots/" ), List.of("commons-io:commons-io:2.12.0-SNAPSHOT") ); } public static List<URL> downloadLibraries(List<String> repositories, List<String> libraries) throws DependencyResolutionException, MalformedURLException { // setup connection var locator = MavenRepositorySystemUtils.newServiceLocator(); locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); locator.addService(TransporterFactory.class, HttpTransporterFactory.class); var repoSystem = locator.getService(RepositorySystem.class); var session = MavenRepositorySystemUtils.newSession(); session.setChecksumPolicy(RepositoryPolicy.CHECKSUM_POLICY_FAIL); session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_NEVER); session.setLocalRepositoryManager(repoSystem.newLocalRepositoryManager(session, new LocalRepository(LOCAL_REPO_DIR))); session.setTransferListener(new LoggingTransferListener()); session.setReadOnly(); List<RemoteRepository> remoteRepos = new ArrayList<>(); var repoIdx = 0; for (var repoUrl : repositories) { remoteRepos.add(new RemoteRepository.Builder(String.valueOf(repoIdx), "default", repoUrl).build()); repoIdx++; } remoteRepos = repoSystem.newResolutionRepositories(session, remoteRepos); // download libraries var request = new DependencyRequest( new CollectRequest( (Dependency) null, libraries.stream().map(library -> new Dependency(new DefaultArtifact(library), null) ).toList(), remoteRepos ), null ); var results = repoSystem.resolveDependencies(session, request).getArtifactResults(); var urls = new ArrayList<URL>(); for (var result : results) { urls.add(result.getArtifact().getFile().toURI().toURL()); } return urls; } private static class LoggingTransferListener extends AbstractTransferListener { @Override public void transferInitiated(TransferEvent event) { System.out.println("Init transfer " + event.getResource().getRepositoryUrl() + event.getResource().getResourceName()); } } }
依赖配置(Kotlin DSL)
implementation("org.apache.maven:maven-resolver-provider:3.8.6") implementation("org.apache.maven.resolver:maven-resolver-connector-basic:1.7.3") implementation("org.apache.maven.resolver:maven-resolver-transport-http:1.8.2")
遇到的问题
- 每次重启程序调用加载器时,解析器会尝试从未获取过该依赖的远程仓库下载
maven-metadata.xml,仅快照依赖存在此现象 - 即使设置了
RepositoryPolicy.UPDATE_POLICY_NEVER,仍会从其他仓库拉取元数据 - 设置
session.setOffline(true)后,尽管依赖已存在于本地仓库(并非从Central仓库下载),仍抛出异常:org.eclipse.aether.resolution.DependencyResolutionException: Cannot access central (https://repo.maven.apache.org/maven2) in offline mode and the artifact (path to artifact) has not been downloaded from it before
解决方案
1. 解决快照依赖元数据重复拉取问题
快照依赖的元数据检查逻辑独立于全局会话配置,需为每个远程仓库单独配置快照策略:
for (var repoUrl : repositories) { RemoteRepository.Builder builder = new RemoteRepository.Builder(String.valueOf(repoIdx), "default", repoUrl); // 显式禁用快照元数据更新检查 RepositoryPolicy snapshotPolicy = new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_NEVER, RepositoryPolicy.CHECKSUM_POLICY_FAIL); builder.setSnapshotPolicy(snapshotPolicy); remoteRepos.add(builder.build()); repoIdx++; }
2. 修复离线模式下的Central仓库异常
Maven Resolver会默认加入Central仓库,需显式禁用默认仓库:
// 初始化会话时添加 session.getSystemProperties().setProperty("maven.resolver.skip.default.repositories", "true");
同时调整CollectRequest的创建逻辑,确保仅使用指定的远程仓库:
var collectRequest = new CollectRequest(); collectRequest.setDependencies(libraries.stream().map(library -> new Dependency(new DefaultArtifact(library), null) ).toList()); collectRequest.setRepositories(remoteRepos); // 禁用默认仓库继承 collectRequest.setRequestContext("standalone"); var request = new DependencyRequest(collectRequest, null);
3. 额外优化
若依赖从非Central仓库下载,可确保本地仓库的_remote.repositories文件中标记了对应来源仓库,避免Resolver误判依赖获取来源。
内容的提问来源于stack exchange,提问作者StudioCode
相关产品推荐
相关产品推荐

