您可能已经注意到我们一直在使用的POM中的依赖项元素。实际上,你一直都在使用外部依赖项,但这里我们会详细讨论它的工作原理。
pom.xml
的dependencies
列表列出了我们的项目需要构建的所有外部依赖项(它是否需要在编译时、测试时、运行时,或者其他什么)。现在,我们的项目只依赖于JUnit(为了清楚起见,我把所有的资源过滤都去掉了):
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
对于每个外部依赖项,您需要至少定义4个东西:groupId
、artifactId
、version
和scope
。groupId
、artifactId
和version
都与pom.xml
中所提供的相同。用于构建该依赖项。scope元素指示您的项目如何使用该依赖项,并且可以是compile
、test
和runtime
时的值。
有了关于依赖关系的信息,Maven将能够在构建项目时引用依赖项。Maven从哪里引用依赖关系?Maven在您的本地存储库中(${user.home}/.m2/repository
是默认的位置)以查找所有的依赖项。在前一节中,我们将该工件从我们的项目(my-app-1.0-SNAPSHOT.jar
)安装到本地存储库中。一旦它安装在那里,另一个项目就可以通过将依赖信息添加到它的pom.xml
:将jar作为依赖项来引用。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<groupId>com.mycompany.app</groupId>
<artifactId>my-other-app</artifactId>
...
<dependencies>
...
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
每当项目引用本地存储库中不可用的依赖项时,Maven将从远程存储库下载依赖项到本地存储库。当您构建第一个项目时,您可能注意到Maven下载了很多东西(这些下载是用于构建项目的各种插件的依赖项)。默认情况下,远程Maven存储库使用可以(浏览)在http://repo.maven.apache.org/maven2/
上找到。您还可以设置自己的远程存储库(可能是公司的中心存储库),而不是使用默认的远程存储库。有关存储库的更多信息,您可以参考存储库的简介。
让我们为我们的项目添加另一个依赖项。假设我们已经在代码中添加了一些日志记录,并且需要将log4j
作为一个依赖项添加。首先,我们需要知道对于log4j
的groupId
、artifactId
和version
是什么。我们可以在浏览器中搜索ibiblio
寻找它,或者使用谷歌搜索“site:www.ibiblio.org maven2 log4j”。搜索显示一个目录名为/maven2/log4j/log4j
(或/pub/packages/maven2/log4j/log4j
)。在该目录中有一个名为maven-metadata.xml
的文件。以下是log4j的maven-metadata.xml
看起来是这样的:
<metadata>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.1.3</version>
<versioning>
<versions>
<version>1.1.3</version>
<version>1.2.4</version>
<version>1.2.5</version>
<version>1.2.6</version>
<version>1.2.7</version>
<version>1.2.8</version>
<version>1.2.11</version>
<version>1.2.9</version>
<version>1.2.12</version>
</versions>
</versioning>
</metadata>
从这个文件中,我们可以看到我们想要的是“log4j
”,而artifactId
是“log4j
”。我们看到许多不同的版本值可供选择;现在,我们将使用最新版本1.2.12(一些maven-metadata.xml
文件还可以指定哪个版本是当前版本的版本)。在maven-metadata.xml
文件,我们可以看到对应于log4j
库的每个版本的目录。在这些文件中,我们将找到实际的jar文件(例如:log4j-1.2.12.jar
)以及pom文件(这是依赖项的pom.xml
,表示它可能拥有的任何进一步的依赖关系以及其他信息)和另一个maven-metadata.xml
文件。还有一个对应于这些文件的md5文件,其中包含了这些文件的md5哈希。您可以使用它来对库进行身份验证,或者找出您可能正在使用的某个特定库的哪个版本。
现在我们已经知道了所需的信息,我们可以将依赖项添加到我们的pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Maven Quick Start Archetype</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
现在,当我们编译这个项目(mvn compile
)时,我们将看到Maven下载log4j
依赖项。
详细的代码可以参考下面的链接:
最后再贴上Maven依赖的范围:
标签名称 | 标签解释 |
---|---|
compile | 这是默认范围,如果没有指定,就使用它。在所有类路径中都可以使用编译依赖项。此外,这些依赖关系被传播到依赖的项目中。 |
provided | 这非常类似于编译,但是表明您希望JDK或容器在运行时提供它。它只在编译和测试类路径中可用,且不具有传递性。 |
runtime | 这个范围表明了对编译的依赖不是必需的,而是用于执行。它在运行时和测试类路径中,而不是编译类路径。 |
test | 该范围表明,对应用程序的正常使用不需要依赖项,并且只适用于测试编译和执行阶段。它不传递。 |
system | 这个范围类似于提供的,除非您必须提供明确地包含它的JAR。工件总是可用的,并且没有在存储库中查找。 |