从Maven中央仓库编程获取依赖项的最简单的Ivy代码

7

我觉得Ivy API非常复杂。

使用Ivy 100%编程方式(无需Ant,无需Xml文件)从Maven Central检索特定本地目录中的构件的最简单代码片段是什么?

以commons-logging:commons-logging:1.1:jar检索到/my/destination为例。


为什么需要使用Ivy?其他库或代码片段可行吗? - kdgregory
当然,如果您有一种备选方案,可以本地缓存并确保下载不会损坏,那也可以。 - Axel Fontaine
1
我原本打算推荐Aether,但是当我看了他们的示例API之后,我意识到为什么人们会嘲笑Java程序员。 - kdgregory
如果您确实需要本地缓存,我建议从Maven Ant任务中调整Dependencies任务。虽然这需要比我想为答案编写的代码更多,但它看起来非常简单(如果您以前没有开发过Ant任务,请从DependenciesTask.javadoExecuteResolution()方法开始)。代码看起来很简单,但您必须构建一个内存中的Maven POM。 - kdgregory
我们这里有一个本地的构建系统(我继承了它),并且使用Ivy进行编程。你说得对,它很复杂,文档也很差。就我而言,我无法弄清楚如何让它下载源代码以及编译后的代码。 - ticktock
2个回答

11

我一直在使用Ivy从Maven仓库远程解析构件(和依赖项)。以下是一个下载单个构件(不包括依赖项)的代码示例。

如果您需要依赖项,则需要调整依赖描述符。

一些注释:

  1. Ivy使用缓存来存储先前检索到的构件及其“ivy翻译”(您将在缓存中找到从Maven构件派生的ivy模块)

  2. 通常的概念是,您以编程方式创建一个Ivy模块,该模块具有对存储在Maven仓库中的“伪模块”的依赖项(即在底层实现了映射的解析器 - 我相信)。

  3. 如果您想知道如何以编程方式使用Ivy的良好起点通常是主类org.apache.ivy.Main


        public static void main(String[] args) throws Exception {

        String groupId = "org.springframework";
        String artifactId = "spring-context-support";
        String version = "4.0.2.RELEASE";
        File   out = new File("out");

        // create an ivy instance
        IvySettings ivySettings = new IvySettings();
        ivySettings.setDefaultCache(new File("ivy/cache"));

        // use the biblio resolver, if you consider resolving 
        // POM declared dependencies
        IBiblioResolver br = new IBiblioResolver();
        br.setM2compatible(true);
        br.setUsepoms(true);
        br.setName("central");

        ivySettings.addResolver(br);
        ivySettings.setDefaultResolver(br.getName());

        Ivy ivy = Ivy.newInstance(ivySettings);

        // Step 1: you always need to resolve before you can retrieve
        //
        ResolveOptions ro = new ResolveOptions();
        // this seems to have no impact, if you resolve by module descriptor (in contrast to resolve by ModuleRevisionId)
        ro.setTransitive(true);
        // if set to false, nothing will be downloaded
        ro.setDownload(true);

        // 1st create an ivy module (this always(!) has a "default" configuration already)
        DefaultModuleDescriptor md = DefaultModuleDescriptor.newDefaultInstance(
            // give it some related name (so it can be cached)
            ModuleRevisionId.newInstance(
                groupId, 
                artifactId+"-envelope", 
                version
            )
        );

        // 2. add dependencies for what we are really looking for
        ModuleRevisionId ri = ModuleRevisionId.newInstance(
            groupId, 
            artifactId,
            version
        );
        // don't go transitive here, if you want the single artifact
        DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(md, ri, false, false, false);

        // map to master to just get the code jar. See generated ivy module xmls from maven repo
        // on how configurations are mapped into ivy. Or check 
        // e.g. http://lightguard-jp.blogspot.de/2009/04/ivy-configurations-when-pulling-from.html
        dd.addDependencyConfiguration("default", "master");
        md.addDependency(dd);

        // now resolve
        ResolveReport rr = ivy.resolve(md,ro);
        if (rr.hasError()) {
            throw new RuntimeException(rr.getAllProblemMessages().toString());
        }

        // Step 2: retrieve
        ModuleDescriptor m = rr.getModuleDescriptor();

        ivy.retrieve(
            m.getModuleRevisionId(),
            out.getAbsolutePath()+"/[artifact](-[classifier]).[ext]",
            new RetrieveOptions()
                // this is from the envelop module
                .setConfs(new String[]{"default"})
        );
    }


我们如何让它同时下载组/工件/版本的源代码? - ticktock
ResolveOptionstransitivedownload 标志具有默认值 true,因此无需调用它们的设置器。 - lyomi
你如何向Ivy设置中添加凭据? - Chris Bolton
1
抱歉,无法回答这些问题。我们已经转向使用Eclipse Aether来访问远程Maven仓库。不记得具体原因了,但在Ivy中确实缺少了一些东西(当然现在可能已经改变了)。 - gnomie
我可以使用CredentialsStore传递凭据。CredentialsStore.INSTANCE.addCredentials(null, host, username, password) - Shkredov S.

8

这有些超出了“100%编程”的范畴,因为它完全避免使用API。 - Axel Fontaine
@AxelFontaine 完成了工作 :-) 如果您遵循第一个示例列表,我有一个调用ivy任务的优美示例。就个人而言,我从未有过使用ivy的Java API的需求。正如David所说,在任何情况下都缺乏文档说明。 - Mark O'Connor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接