本教程将向您展示当一个项目依赖于另一个项目时如何使用Ivy。
对于我们的示例,我们将有两个项目depender和dependee,其中depender项目使用或者需要dependee项目。这个例子将有助于说明Ivy的两个方面:
dependee项目非常简单。它依赖于Apache库的commons-lang,只包含一个类:standalone.Main,它提供两种服务:
Here is the content of the project:
build.xml: the Ant build file for the project
ivy.xml: the project Ivy file
src/standalone/Main.java: the only class of the project
Take a look at the ivy.xml file:
<ivy-module version="1.0">
<info organisation="org.apache" module="dependee"/>
<dependencies>
<dependency org="commons-lang" name="commons-lang" rev="2.0"/>
</dependencies>
</ivy-module>
The Ivy file declares only one dependency, that being the Apache commons-lang library.(Ivy文件只声明了一个依赖项,即Apache commons-lang库)
depender项目也非常简单。它在dependee项目的最新版本上只声明了一个依赖项,并且只包含一个类,depending.Main,该类执行两个操作:
Take a look at the ivy.xml file:
<ivy-module version="1.0">
<info organisation="org.apache" module="depender"/>
<dependencies>
<dependency name="dependee" rev="latest.integration"/>
</dependencies>
</ivy-module>
The Ivy settings are defined in two files located in the settings directory:
Let’s have a look at the ivysettings.xml file:
<ivysettings>
<properties file="${ivy.settings.dir}/ivysettings.properties"/>
<settings defaultResolver="libraries"/>
<caches defaultCacheDir="${ivy.settings.dir}/ivy-cache"/>
<resolvers>
<filesystem name="projects">
<artifact pattern="${repository.dir}/[artifact]-[revision].[ext]"/>
<ivy pattern="${repository.dir}/[module]-[revision].xml"/>
</filesystem>
<ibiblio name="libraries" m2compatible="true" usepoms="false"/>
</resolvers>
<modules>
<module organisation="org.apache" name="dependee" resolver="projects"/>
</modules>
</ivysettings>
The file contains four main tags: properties, settings, resolvers and modules.(该文件包含四个主要标记:属性、设置、解析器和模块。)
This tag loads some properties for the Ivy process, just like Ant does.
这个标记为Ivy进程加载一些属性,就像Ant一样。
This tag initializes some parameters for the Ivy process. In this case, the directory that Ivy will use to cache artifacts will be in a sub directory called ivy-cache of the directory containing the ivysettings.xml file itself. The second parameter, tells Ivy to use a resolver named “libraries” as its default resolver. More information can be found in the settings reference documentation.(这个标签初始化Ivy进程的一些参数。在本例中,Ivy将用于缓存工件的目录将位于包含工件的目录中名为ivy-cache的子目录中ivysettings.xml文件本身。第二个参数告诉Ivy使用名为“libraries”的解析器作为其默认解析器。更多信息可以在设置参考文档中找到。)
This tag defines the resolvers to use. Here we have two resolvers defined: “projects” and “libraries”. The filesystem resolver called “projects” is able to resolve the internal dependencies by locating them on the local filesystem. The ibiblio resolver called “libraries” is able to find dependencies on the Maven 2 repository, but doesn’t use Maven POMs.(此标记定义要使用的解析器。这里我们定义了两个解析器:“projects”和“libraries”。名为“projects”的文件系统解析器能够通过在本地文件系统上定位内部依赖项来解析它们。名为“libraries”的ibiblio解析器能够找到Maven 2存储库上的依赖项,但不使用Maven POMs。)
The modules tag allows you to configure which resolver should be used for which module. Here the setting tells Ivy to use the “projects” resolver for all modules having an organisation of org.apache and module name of dependee. This actually corresponds to only one module, but a regular expression could be used, or many other types of expressions (like glob expressions).
(modules标签允许您配置哪个解析器应该用于哪个模块。这里的设置告诉Ivy对所有组织为org.apache、模块名为dependee的模块使用“projects”解析器。这实际上只对应于一个模块,但是可以使用正则表达式,或者许多其他类型的表达式(比如glob表达式))
All other modules (i.e. all modules but org.apache#dependee), will use the default resolver (“libraries”).
(所有其他模块(即除org.apache#dependee这个模块之外的所有模块),将使用默认的解析器(“libraries”)。)
Open a shell (or command line) window, and go to the src/example/dependence directory.
At the prompt, type: ant This will clean up the entire project directory tree. You can do this each time you want to clean up this example.
Go to dependee directory and publish the project
[ivy@apache:/ivy/dependence/dependee]$ ant publish
Buildfile: /ivy/dependence/dependee/build.xml
resolve:
[ivy:retrieve] :: Apache Ivy 2.5.0 - 20191020104435 :: https://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: org.apache#dependee;working@apache
[ivy:retrieve] confs: [default]
[ivy:retrieve] found commons-lang#commons-lang;2.6 in libraries
[ivy:retrieve] downloading https://repo1.maven.org/maven2/commons-lang/commons-lang/2.6/commons-lang-2.6.jar ...
[ivy:retrieve] ............................. (277kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] commons-lang#commons-lang;2.6!commons-lang.jar (1690ms)
[ivy:retrieve] :: resolution report :: resolve 1143ms :: artifacts dl 1693ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 1 | 1 | 0 | 0 || 1 | 1 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.apache#dependee
[ivy:retrieve] confs: [default]
[ivy:retrieve] 1 artifacts copied, 0 already retrieved (277kB/5ms)
compile:
[mkdir] Created dir: /ivy/dependence/dependee/build/classes
[javac] Compiling 1 source file to /ivy/dependence/dependee/build/classes
jar:
[propertyfile] Creating new property file: /ivy/dependence/dependee/build/classes/version.properties
[jar] Building jar: /ivy/dependence/dependee/build/dependee.jar
publish:
[ivy:publish] :: delivering :: org.apache#dependee;working@apache :: 1 :: release :: Sun Oct 20 11:25:11 IST 2019
[ivy:publish] delivering ivy file to /ivy/dependence/dependee/build/ivy.xml
[ivy:publish] :: publishing :: org.apache#dependee
[ivy:publish] published dependee to /ivy/dependence/settings/repository/dependee-1.jar
[ivy:publish] published ivy to /ivy/dependence/settings/repository/dependee-1.xml
[echo] project dependee released with version 1
BUILD SUCCESSFUL
Total time: 8 seconds
What we see here:
the project depends on 1 library (1 artifact)
the library was not in the Ivy cache and so was downloaded (1 downloaded)
the project has been released under version number 1
As you can see, the call to the publish task has resulted in two main things:
the delivery of a resolved Ivy file to build/ivy.xml.
This has been done because by default, the publish task not only publishes artifacts, but also its Ivy file. So it has looked to the path where the Ivy file to publish should be, using the artifactspattern: ${build.dir}/[artifact].[ext]. For an Ivy file, this resolves to build/ivy.xml. Because this file does not exist, it automatically makes a call to the deliver task which delivers a resolved Ivy file to this destination.
the publication of artifact ‘dependee’ and its resolved Ivy file to the repository.
Both are just copies of the files found in the current project, or more precisely, those in the build directory. This is because the artifactspattern has been set to ${build.dir}/[artifact].[ext], so the dependee artifact is found at build/dependee.jar and the Ivy file in build/ivy.xml. And because we have asked the publish task to publish them using the “projects” resolver, these files are copied to repository/dependee-1.jar and to repository/dependee-1.xml, respecting the artifact and Ivy file patterns of our settings (see above).
Go to directory depender and run ant
[ivy@apache:/ivy/dependence/depender]$ ant
Buildfile: /ivy/dependence/depender/build.xml
clean:
resolve:
[ivy:retrieve] :: Apache Ivy 2.5.0 - 20191020104435 :: https://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: org.apache#depender;working@apache
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.apache#dependee;1 in projects
[ivy:retrieve] [1] org.apache#dependee;latest.integration
[ivy:retrieve] found commons-lang#commons-lang;2.6 in libraries
[ivy:retrieve] downloading /ivy/dependence/settings/repository/dependee-1.jar ...
[ivy:retrieve] .. (1kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] org.apache#dependee;1!dependee.jar (6ms)
[ivy:retrieve] :: resolution report :: resolve 89ms :: artifacts dl 10ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 2 | 1 | 1 | 0 || 2 | 1 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.apache#depender
[ivy:retrieve] confs: [default]
[ivy:retrieve] 2 artifacts copied, 0 already retrieved (279kB/7ms)
compile:
[mkdir] Created dir: /ivy/dependence/depender/build/classes
[javac] Compiling 1 source file to /ivy/dependence/depender/build/classes
run:
[java] you are using version 1 of class standalone.Main
[java] standard message : i am depending.Main and standalone.Main will do the job for me
[java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils
[java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me
BUILD SUCCESSFUL
Total time: 6 seconds
What we see here:
the project depends on 2 libraries (2 artifacts)
one of the libraries was in the cache because there was only 1 download (1 downloaded)
Ivy retrieved version 1 of the project “dependee”. The call to standalone.Main.getVersion() has returned 1. If you look in the depender/lib directory, you should see dependee-1.jar which is the version 1 artifact of the project “dependee”
the call to standalone.Main.capitalizeWords(str) succeed, which means that the required library was in the classpath. If you look at the lib directory, you will see that the library commons-lang-2.0.jar was also retrieved. This library was declared as a dependency of the “dependee” project, so Ivy retrieves it (transitively) along with the dependee artifact.
(项目依赖于2个库(2个工件)
其中一个库在缓存中,因为只有1个下载(1个已下载)
Ivy检索到了项目“dependee”的第1版。呼叫独立.Main.getVersion()已返回1。如果您查看depender/lib目录,您应该会看到dependee-1.jar,它是项目“dependee”的版本1工件
对该方法的调用成功,这意味着所需的库位于类路径中。如果查看lib目录,您将看到还检索到了库commons-lang-2.0.jar。该库被声明为“dependee”项目的依赖项,因此Ivy(可传递地)将其与dependee工件一起检索。)
Like we did before in step 3, publish the dependee project again. This will result in a new version of the project being published.
(就像我们之前在步骤3中所做的那样,再次发布dependee项目。这将导致发布项目的新版本。)
[ivy@apache:/ivy/dependence/dependee]$ ant publish
Buildfile: /ivy/dependence/dependee/build.xml
resolve:
[ivy:retrieve] :: Apache Ivy 2.5.0 - 20191020104435 :: https://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: org.apache#dependee;working@apache
[ivy:retrieve] confs: [default]
[ivy:retrieve] found commons-lang#commons-lang;2.6 in libraries
[ivy:retrieve] :: resolution report :: resolve 62ms :: artifacts dl 3ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 1 | 0 | 0 | 0 || 1 | 0 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.apache#dependee
[ivy:retrieve] confs: [default]
[ivy:retrieve] 0 artifacts copied, 1 already retrieved (0kB/3ms)
compile:
jar:
[propertyfile] Updating property file: /ivy/dependence/dependee/build/classes/version.properties
[jar] Building jar: /ivy/dependence/dependee/build/dependee.jar
publish:
[delete] Deleting: /ivy/dependence/dependee/build/ivy.xml
[ivy:publish] :: delivering :: org.apache#dependee;working@apache :: 2 :: release :: Sun Oct 20 11:25:23 IST 2019
[ivy:publish] delivering ivy file to /ivy/dependence/dependee/build/ivy.xml
[ivy:publish] :: publishing :: org.apache#dependee
[ivy:publish] published dependee to /ivy/dependence/settings/repository/dependee-2.jar
[ivy:publish] published ivy to /ivy/dependence/settings/repository/dependee-2.xml
[echo] project dependee released with version 2
BUILD SUCCESSFUL
Total time: 5 seconds
Now if you look in your repository folder, you will find 2 versions of the dependee project. Let’s look at it:
(现在,如果您查看存储库文件夹,您将发现dependee项目的两个版本。我们来看看:)
I:\dependee>dir ..\settings\repository /w
[.] [..] dependee-1.jar dependee-1.xml dependee-2.jar dependee-2.xml
I:\dependee>
OK, now our repository contains two versions of the project dependee, so other projects can refer to either version.
(好的,现在我们的存储库包含两个版本的项目dependee,所以其他项目可以引用这两个版本。)
What should we expect if we run the depender project again? It should:
(如果我们再次运行depender项目,我们应该期望什么?它应该:)
Let’s try it!!
[ivy@apache:/ivy/dependence/depender]$ ant
Buildfile: /ivy/dependence/depender/build.xml
clean:
resolve:
[ivy:retrieve] :: Apache Ivy 2.5.0 - 20191020104435 :: https://ant.apache.org/ivy/ ::
[ivy:retrieve] :: loading settings :: file = /ivy/dependence/settings/ivysettings.xml
[ivy:retrieve] :: resolving dependencies :: org.apache#depender;working@apache
[ivy:retrieve] confs: [default]
[ivy:retrieve] found org.apache#dependee;2 in projects
[ivy:retrieve] [2] org.apache#dependee;latest.integration
[ivy:retrieve] found commons-lang#commons-lang;2.6 in libraries
[ivy:retrieve] downloading /ivy/dependence/settings/repository/dependee-2.jar ...
[ivy:retrieve] .. (1kB)
[ivy:retrieve] .. (0kB)
[ivy:retrieve] [SUCCESSFUL ] org.apache#dependee;2!dependee.jar (5ms)
[ivy:retrieve] :: resolution report :: resolve 100ms :: artifacts dl 10ms
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 2 | 1 | 1 | 0 || 2 | 1 |
---------------------------------------------------------------------
[ivy:retrieve] :: retrieving :: org.apache#depender
[ivy:retrieve] confs: [default]
[ivy:retrieve] 2 artifacts copied, 0 already retrieved (279kB/6ms)
compile:
[mkdir] Created dir: /ivy/dependence/depender/build/classes
[javac] Compiling 1 source file to /ivy/dependence/depender/build/classes
run:
[java] you are using version 2 of class standalone.Main
[java] standard message : i am depending.Main and standalone.Main will do the job for me
[java] [standalone.Main] capitalizing string "i am depending.Main and standalone.Main will do the job for me" using org.apache.commons.lang.WordUtils
[java] capitalized message : I Am Depending.main And Standalone.main Will Do The Job For Me
BUILD SUCCESSFUL
Total time: 6 seconds
OK, we got what we expected as the run target shows that we are using version 2 of the main class of the dependee project. If we take a look at the resolve target results, we see that one artifact has been downloaded to the Ivy cache. In fact, this file is the same version 2 of the dependee project that is in the repository, but now all future retrievals will pull it from your ivy-cache directory.(好的,我们得到了预期的结果,因为run目标显示我们正在使用dependee项目的主类的版本2。如果我们查看resolve target结果,就会发现有一个工件已下载到Ivy缓存中。事实上,该文件与存储库中的dependee项目的版本2相同,但现在所有将来的检索都将从ivy缓存目录中提取该文件。)