项目B:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>B</artifactId>
<packaging>pom</packaging>
<name>B</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>maven</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>

假设A就是上一个例子中定义的POM,那么最终的结果也是一致的。除了在B中定义的d模块,所有A的管理依赖都会导入到B中。

项目X:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>X</artifactId>
<packaging>pom</packaging>
<name>X</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

项目Y:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>Y</artifactId>
<packaging>pom</packaging>
<name>Y</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

项目Z:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>Z</artifactId>
<packaging>pom</packaging>
<name>Z</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>maven</groupId>
<artifactId>X</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>maven</groupId>
<artifactId>Y</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

在上面的例子中,Z导入了X和Y的管理依赖。不过有个问题,X和Y都包含了依赖a。在这里,会使用1.1版本的a,因为X先被声明,并且a没有在Z的依赖管理中声明。

这个过程是递归进行的。假如X导入了另外的POM,Q,那么当解析Z的时候,所有Q的管理依赖看上去就都像在X中定义的一样。

当定义一个用于构建多项目的包含一些相关构件的依赖“库”时,导入依赖就十分有效。从“库”中引用一个或多个构件到项目中,是一种很常见的做法。然而,
保持项目中使用的依赖版本与库中发布的版本一致会有点麻烦。下面的模式描述了怎么生成一个供其它项目使用的“物料清单”(BOM)。

项目的根元素是BOM pom文件。它定义了库中创建的所有构件版本。其它要使用该库的项目必须将该pom导入到其pom文件中的<dependencyManagement>元素中。

<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.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project1Version>1.0.0</project1Version>
<project2Version>1.0.0</project2Version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project1Version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>parent</module>
</modules>
</project>

parent子项目将BOM pom作为它的父项目。这是一个简单的多项目pom。

<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.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project1Version>1.0.0</project1Version>
<project2Version>1.0.0</project2Version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project1Version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>parent</module>
</modules>
</project>

接下来是真正的pom文件。

<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>
<parent>
<groupId>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
</project>

<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>
<parent>
<groupId>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project2Version}</version>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
</project>

下面的例子说明了怎么在项目中使用“库”,而不必指定依赖模块的版本。

<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.test</groupId>
<artifactId>use</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
</dependency>
</dependencies>
</project>

最后,当创建引入依赖的项目时,需要注意以下几点:

  • 不要尝试引入在当前pom中定义的子模块pom。那会导致不能定位pom和编译失败。
  •  绝不要声明导入其他pom作为目标pom的父项目(或者祖父项目等)的pom文件。这会导致循环解析,并触发异常。
  •  当引用有传递性依赖的模块时,需要指定依赖模块的版本。不这样做,这些模块可能没有确定的版本,从而导致编译失败。(这在任何情况下都应该是一个最佳实践,因为它保证了模块版本的不变性)

系统依赖

系统范围的依赖应该是一直可用,并且Maven不会去仓库中查找。系统范围依赖通常是指JDK或者VM提供的依赖。所以,系统依赖适用于这种情况:以前可以单独获取,但现在是由JDK提供的依赖。典型的例子就是JDBC标准扩展或者Java认证和授权服务(JAAS)。一个简单的例子如下:

<project>

<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>

</project>

如果你的构件依赖于JDK的tools.jar,那么系统路径的值如下所示:

<project>

<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>

</project>