我们正在使用maven 2.1.0。我有多个完全独立的模块,但仍然有许多常见的依赖项。像log4J,但有些模块不需要它。我想知道在<dependencyManagement>
部分的一个父文件中声明所有公共依赖项是否是一个好主意,还是有更好的方法来解决这个问题?
关于<dependencyManagement>
的后续问题。如果我在父项的<dependencyManagement>
部分中声明Log4J并且子项目不使用它,那么它是否会被包括在内?
答案 0 :(得分:33)
如果您有父项目,则可以在父pom的dependencyManagement部分中声明所有依赖项及其版本。这个不意味着所有项目都将使用所有这些依赖项,这意味着如果项目确实声明了依赖项,它将继承配置,因此它只需要声明依赖项的groupId和artifactId 。您甚至可以在父级的dependencyManagement中声明子项目而不引入循环。
请注意,您也可以通过在pluginManagement部分中声明插件来实现与插件类似的操作。这意味着声明该插件的任何子代都将继承该配置。
例如,如果你有4个项目,父,核心, ui 和 utils ,你可以在父级中声明所有外部依赖项和内部项目版本。然后子项目继承它们声明的任何依赖项的配置。如果所有模块都具有相同的版本,则甚至可以将这些模块声明为父级中的属性。
示例父母如下:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>ui</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>utils</module>
<module>core</module>
<module>ui</module>
</modules>
</project>
utils,core和ui项目继承了所有相关版本。 utils的:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
<!--note version not declared as it is inherited-->
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>
核心:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>utils</artifactId>
</dependency>
</dependencies>
UI:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>ui</artifactId>
<parent>
<artifactId>parent</artifactId>
<groupId>name.seller.rich</groupId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
</dependency>
</dependencies>
</project>
答案 1 :(得分:16)
我写了一份best practices的清单。这是最重要的。
答案 2 :(得分:8)
每个模块都应该有自己的POM,并声明自己的依赖关系。这不仅跟踪外部依赖关系,还跟踪内部依赖关系。
当您使用Maven构建项目时,它会对整个项目进行排序。因此,如果许多模块(可能全部)依赖于log4j,那么它将只包含一次。如果您的模块依赖于不同版本的log4j,则存在一些问题,但这种方法通常可以正常工作。
(如果有超过1-2个开发人员一起工作)设置内部存储库(如Artifactory)并在内部使用它也很有用。这使得处理不在公共存储库中的库变得更容易(只需将其添加到您的内部存储库!)并且您还可以使用构建工具来推送您自己的代码的构建,以便其他人可以使用这些模块而无需检出代码(在大型项目中有用)
答案 3 :(得分:1)
关于的后续问题。如果我在父项的部分中声明Log4J并且子项目不使用它,那么它是否会被包括在内?
没有。依赖管理只设置默认版本和可能的范围(我已经看到这两个看起来都是继承的,似乎没有继承,所以你需要自己查看这个)。要在子模块中包含依赖项,您需要将其声明为模块的依赖项并省略version元素。您可以覆盖子模块中的默认值,只需在子模块的POM的dependency元素中包含版本号。
我有多个完全独立的模块,但仍然有很多共同的依赖。
在这种情况下,是和否。
对于作为统一项目一起构建,版本化和部署的模块,例如组成单个Web应用程序的模块,绝对是肯定的。当您决定转移到新版本的依赖项时,您希望减轻自己在多个POM中更改版本的麻烦。当您需要排除某些传递依赖项时,它还可以节省您的工作量。如果您在该部分中使用其排除声明依赖项,则不必在多个POM中维护排除项。
对于不直接相关但在公司内部的单个团队中构建的模块,您可能需要考虑为常用库声明默认版本,例如测试实用程序,日志实用程序等,以使团队使用标准您已定义为最佳实践的一部分的工具版本。请记住,当您标准化一组新的公共库时,您总是可以增加超级POM的版本。您在标准化库和工具之间划清界限,项目特定的库和工具由您决定,但您的团队应该很容易找到。
答案 4 :(得分:1)
我们为所有项目使用具有dependencyManagement块的单个公共父级。当我们将更多项目移动到maven时,这开始崩溃 - 如果项目需要不同的版本,那么我们必须将其声明为所有子项的依赖项,或者明确定义每个相关子项的版本。
我们正在尝试一种模型,我们将dependencyManagement从我们的普通父级拆分出来,然后将我们的公司dependencyManagement pom导入顶层项目pom。这允许我们有选择地定义覆盖公司默认值的项目默认值。
以下是原始方案:
A defines version 1.0 of foo.jar as the corporate default
B child of A
C1, C2, C3 children of B
D1, D2, D3 children of C1, C2, C3 respectively
如果D1和D2需要foo.jar的1.1版本,那么我们的选择是:
以下是我们正在尝试的内容:
A defines version 1.0 of foo.jar as the corporate default
B dependencyManagement: imports A, declares a default of foo.jar version 1.1
C1, C2, C3 children of B
D1, D2, D3 children of C1, C2, C3 respectively
现在D1和D2只是声明对foo.jar的依赖,并从B的dependencyManagement块中获取版本1.1。
答案 5 :(得分:0)
在多模块项目中,我将任何公共依赖项放在父pom.xml的元素中。如果模块与同一个项目无关,我不确定这是否是最佳实践。