如何使用 Maven Artifact Resolver 列出可传递依赖项?

How can I use Maven Artifact Resolver to list transitive dependencies?

提问人:Cardinal System 提问时间:10/26/2022 最后编辑:Cardinal System 更新时间:4/11/2023 访问量:390

问:

我正在为我的公司开发一个应用程序,该应用程序需要解决 maven 项目的依赖关系。这是一个独立的应用程序,而不是 maven 插件。我目前唯一要做的就是打印已解决的依赖项以确认已找到它们。我正在使用 Apache Maven 模型 ()、Apache Maven Artifact Resolver () 和 Maven Artifact Resolver Implementation () 来支持我的工作。 v4.0.0-alpha-2v1.8.2v1.8.2

最初的设置确实让我感到疲软。我没有运气找到最新的更新示例或文档。这是我起草的代码:

public static void main(String[] args)
        throws LoadException, IOException, XmlPullParserException, DependencyResolutionException {
    MavenXpp3Reader reader = new MavenXpp3Reader();
    Model model = reader.read(new FileReader(new File("C:\\Users\\lc70844\\eclipse-workspace\\test\\pom.xml")));

    DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
    DefaultRepositorySystem repositorySystem = new DefaultRepositorySystem();

    for (Dependency dependency : model.getDependencies()) {
        DependencyRequest request = new DependencyRequest();
        request.setRoot(new DefaultDependencyNode(
                new org.eclipse.aether.graph.Dependency(toArtifact(dependency), dependency.getScope())));
        DependencyResult result = repositorySystem.resolveDependencies(session, request);
        result.getArtifactResults().stream().map(a -> a.getArtifact())
                .map(a -> a.getGroupId() + ":" + a.getArtifactId() + ":" + a.getVersion()).forEach(System.out::println);
    }
}

它抛出一个异常,指出“存储库系统会话的本地存储库管理器不能为空”。这是不言自明的;我们都知道我需要做什么。但是,DefaultRepositorySystemSession#setLocalRepositoryManager(LocalRepositoryManager) 需要一个参数,这是我在弄清楚如何设置时遇到的问题。我想使用的存储库是位于以下位置的本地存储库: 。LocalRepositoryManager%userprofile%/.m2/repository

我发现了一些与我的问题有关的类似问题,但它们似乎具有错误的上下文,或者正在使用已弃用的库来实现其目的。我希望有一个可靠的、最新的解决方案。

希望我至少朝着正确的方向前进。我还需要做些什么来获取我的依赖项列表?

编辑

我目前的方法是使用 Maven Invoker 来运行,但这只是暂时的,并不是真正的解决方案。启动 Maven 进程需要很长时间,并且解析日志输出以获取文件路径并不是干净的方法。我正在努力使我的应用程序更有效率,而使用 Maven Invoker 不是一种有效的方法。mvn dependency:list

Java Apache Maven 依赖 Aether

评论


答:

1赞 Sergey Tsypanov 3/21/2023 #1

好吧,如果您有权访问目标,则可以简单地执行这将打印所有依赖项的完整树及其范围(显式指定和传递)。 输出如下所示:pom.xmlmvn dependency:tree

[INFO] com.tsypanov:spring-boot-benchmark:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter:jar:2.6.3:compile
[INFO] |  +- org.springframework.boot:spring-boot:jar:2.6.3:compile
[INFO] |  |  \- org.springframework:spring-context:jar:5.3.15:compile
[INFO] |  |     \- org.springframework:spring-expression:jar:5.3.15:compile
[INFO] |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.6.3:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.6.3:compile
[INFO] |  |  +- ch.qos.logback:logback-classic:jar:1.2.10:compile
[INFO] |  |  |  \- ch.qos.logback:logback-core:jar:1.2.10:compile
[INFO] |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.17.1:compile
[INFO] |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.17.1:compile
[INFO] |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.33:compile
...

或者,如果您需要解析输出,则使用 or 会更容易。请注意,这只是打印模型,并没有说明特定依赖项是否被解析和缓存,但您可以使用以下输出进行检查: 只需拆分输出行,如下所示mvn dependency:listmvn dependency:build-classpath.m2mvn dependency:classpath

[INFO] Dependencies classpath:
C:\Users\STsypanov\.m2\repository\org\springframework\boot\spring-boot-starter\2.6.3\spring-boot-starter-2.6.3.jar;C:\Users\STsypanov\.m2\repository\org\springframework\boot\spring-boot\2.6.3\spring-boot-2.6.3.jar;

,然后检查每个文件是否存在:;

String[] paths = classpath.split(";");
for (String path : paths) {
  var file = new File(path);
  if (file.exists()) {
    //...
  }
}

评论

1赞 Cardinal System 3/24/2023
这不是我想要的答案,但唉,这是唯一的答案。我想我现在必须继续以缓慢的方式做事:(