3.Maven依赖管理
企业级项目通常依赖于各种开源库。考虑您希望将Log4J用于应用程序日志记录的情况。要完成这个,你会去Log4J下载页面,下载JAR文件,并把它放在你的项目的lib文件夹或添加到项目的类路径。正如你可能已经知道,这种方法有几个问题:
您需要将JAR文件检查为SVN,以便您的项目可以在除您自己的计算机之外的计算机上构建。
您下载的JAR文件可能依赖于其他几个库。您现在必须搜索所有这些依赖项并将它们添加到您的项目。
当升级JAR文件的时候,您需要重新启动该过程。
很难在组织内的各个团队之间共享JAR文件。
为了解决这些问题,Maven提供了声明性依赖关系管理。使用这种方法,可以在名为pom.xml的外部文件中声明项目的依赖关系。 Maven将自动下载这些依赖项并将它们移交到您的项目中,以便构建,测试或打包。
图3-1显示了Maven的依赖关系管理的高级视图。正如你可以看到,Maven与保存工件和相关元数据的仓库进行交互。通常通过Web访问的存储库被认为是远程的,并由第三方维护。 Maven与之交互的默认远程存储库称为Maven Central,它位于repo.maven.apache.org和uk.maven.org。 Maven将下载的工件放在本地存储库中。
图3-1。 Maven依赖管理
尽管图3-1中所示的架构在大多数情况下都有效,但它在企业环境中提出了一些问题。第一个问题是在团队之间共享公司相关的工件是不可能的。由于安全和知识产权问题,您不想在Maven Central上发布企业的工件。另一个问题涉及法律和许可问题。您的公司可能希望团队只使用官方批准的开源软件,这种架构不适合该模型。最后一个问题涉及带宽和下载速度。在Maven Central上的负载过重的情况下,Maven工件的下载速度降低,这可能对您的构建产生负面影响。因此,大多数企业采用如图3-2所示的架构。
表3-1。开源资源库管理器
资源库管理器 网址
Sonatype Nexus
www.sonatype.com/nexus
Apache Archiva
http://archiva.apache.org/
人工制品
www.jfrog.com/open-source/
使用存储库
为了使用新的存储库,您需要修改settings.xml文件。清单3-1显示了添加到settings.xml文件中的Spring和JBoss存储库。以同样的方式,您可以添加到您公司的存储库管理器。
列表3-1。在settings.xml中添加存储库
注意有关存储库的信息可以在settings.xml或pom.xml文件中提供。每种方法都有利弊。将库信息放在pom.xml文件中可以使构建可移植。它使开发人员能够下载项目并简单地构建它们,而无需对其本地settings.xml文件进行任何进一步的修改。这种方法的问题是,当工件被释放时,相应的pom.xml文件将在其中硬编码存储库信息。如果存储库URL有变化,这些工件的消费者将由于存储库路径损坏而遇到错误。将存储库信息放在settings.xml文件中解决了这个问题,并且由于它提供的灵活性,通常在企业设置中推荐settings.xml方法。
依赖性标识
Maven依赖项通常是归档,如JAR,WAR,企业归档(EAR)和ZIP。每个Maven依赖项使用以下组,工件和版本(GAV)坐标唯一标识:
groupId:负责此项目的组织或组的标识符。示例包括org.hibernate,log4j和org.springframework.boot。
artifactId:项目生成的工件的标识符。这在使用相同groupId的项目中必须是唯一的。示例包括hibernate-tools,log4j,spring-core等。
version:表示项目的版本号。示例包括1.0.0,2.3.1-SNAPSHOT和4.3.6.Final。
type:表示生成的工件的打包。示例包括JAR,WAR和EAR。
传递依赖
在项目的pom.xml文件中声明的依赖项通常有自己的依赖项。这样的依赖关系称为传递依赖关系。以Hibernate Core为例。为了使其正常工作,它需要JBoss Logging,dom4j,javaassist等。在你的pom.xml文件中声明的Hibernate Core被认为是一个直接的依赖,诸如dom4j和javaassist之类的依赖被认为是你项目的传递依赖。 Maven的一个主要优点是它自动处理传递依赖并将它们包括在项目中。
图3-3提供了传递依赖的一个例子。注意传递依赖可以有自己的依赖。你可能想象,这可以迅速变得复杂,特别是当多个直接依赖拉不同版本的同一个JAR文件。
图3-3。传递依赖
Maven使用一种称为依赖性中介的技术来解决版本冲突。简单地说,依赖调解允许Maven拉出最接近树中项目的依赖。在图3-3中,有两个版本的依赖B:0.0.8和1.0.0。在这种情况下,版本0.0.8的依赖项B包含在项目中,因为它是一个直接依赖项并且最靠近树。现在看看依赖F的三个版本:0.1.3,1.0.0和2.2.0。所有三个依赖都在同一深度。在这种情况下,Maven将使用第一个找到的依赖项,这将是0.1.3,而不是最新的2.2.0版本。
考虑一个使用JUnit进行单元测试的项目。您在项目中包含的JUnit JAR文件仅在测试期间需要。您确实不需要将JUnit JAR绑定到最终的生产归档中。同样,考虑MySQL数据库驱动程序,mysql-connector-java.jar文件。当您在容器(如Tomcat)中运行应用程序时,需要依赖关系。 Maven使用范围的概念,它允许您指定何时何地需要特定的依赖关系。
Maven提供以下六个范围:
compile:在项目构建,测试和运行的所有阶段的类路径中都提供了与编译范围的依赖关系。这是默认范围。
provided:在构建和测试阶段期间,类路径中提供了与提供的作用域的依赖关系。它们不会在生成的工件中捆绑。使用此范围的依赖关系的示例包括Servlet api,JSP api等。
runtime:在构建阶段期间,类路径中不具有运行时作用域的依赖关系。相反,它们被捆绑在生成的工件中,并在运行时可用。
test 测试:在测试阶段与测试范围的依赖关系可用。 JUnit和TestNG是测试范围的依赖的好例子。
system:与系统范围的依赖关系与提供作用域的依赖关系类似,但不从存储库检索这些依赖关系。相反,指定文件系统的硬编码路径,从中使用依赖性。
import:导入范围仅适用于.pom文件依赖项。它允许您包括来自远程.pom文件的依赖关系管理信息。导入范围仅在Maven 2.0.9或更高版本中可用。
手动依赖安装
理想情况下,您将从公共存储库或企业存储库管理器拉取项目中的依赖项。但是,有时您需要在本地存储库中提供存档,以便您可以继续开发。例如,您可能正在等待系统管理员将所需的JAR文件添加到企业存储库管理器。
Maven提供了一种方便的方式使用安装插件将存档安装到本地存储库中。清单3-2安装位于c:\ apress \ gswm-book \ chapter3文件夹中的test.jar文件。
清单3-2。手动安装依赖关系
总结
依赖管理是Maven的核心。 每个不平凡的Java项目都依赖于开源或外部工件,Maven的依赖关系管理自动化检索这些工件并将它们包含在构建过程的正确阶段的过程。 您还了解到Maven使用GAV坐标来识别其工件。
在下一章中,您将了解一个基本的Maven项目的组织
企业级项目通常依赖于各种开源库。考虑您希望将Log4J用于应用程序日志记录的情况。要完成这个,你会去Log4J下载页面,下载JAR文件,并把它放在你的项目的lib文件夹或添加到项目的类路径。正如你可能已经知道,这种方法有几个问题:
您需要将JAR文件检查为SVN,以便您的项目可以在除您自己的计算机之外的计算机上构建。
您下载的JAR文件可能依赖于其他几个库。您现在必须搜索所有这些依赖项并将它们添加到您的项目。
当升级JAR文件的时候,您需要重新启动该过程。
很难在组织内的各个团队之间共享JAR文件。
为了解决这些问题,Maven提供了声明性依赖关系管理。使用这种方法,可以在名为pom.xml的外部文件中声明项目的依赖关系。 Maven将自动下载这些依赖项并将它们移交到您的项目中,以便构建,测试或打包。
图3-1显示了Maven的依赖关系管理的高级视图。正如你可以看到,Maven与保存工件和相关元数据的仓库进行交互。通常通过Web访问的存储库被认为是远程的,并由第三方维护。 Maven与之交互的默认远程存储库称为Maven Central,它位于repo.maven.apache.org和uk.maven.org。 Maven将下载的工件放在本地存储库中。
图3-1。 Maven依赖管理
尽管图3-1中所示的架构在大多数情况下都有效,但它在企业环境中提出了一些问题。第一个问题是在团队之间共享公司相关的工件是不可能的。由于安全和知识产权问题,您不想在Maven Central上发布企业的工件。另一个问题涉及法律和许可问题。您的公司可能希望团队只使用官方批准的开源软件,这种架构不适合该模型。最后一个问题涉及带宽和下载速度。在Maven Central上的负载过重的情况下,Maven工件的下载速度降低,这可能对您的构建产生负面影响。因此,大多数企业采用如图3-2所示的架构。
图3-2。企业Maven存储库体系结构
内部存储库管理器充当远程存储库的代理。由于您可以完全控制内部存储库,因此可以调整公司允许的工件类型。此外,您还可以将组织的工件推送到服务器上,从而实现协作。有几个开源库管理器。表3-1仅列出了其中的一些。表3-1。开源资源库管理器
资源库管理器 网址
Sonatype Nexus
www.sonatype.com/nexus
Apache Archiva
http://archiva.apache.org/
人工制品
www.jfrog.com/open-source/
使用存储库
为了使用新的存储库,您需要修改settings.xml文件。清单3-1显示了添加到settings.xml文件中的Spring和JBoss存储库。以同样的方式,您可以添加到您公司的存储库管理器。
列表3-1。在settings.xml中添加存储库
注意有关存储库的信息可以在settings.xml或pom.xml文件中提供。每种方法都有利弊。将库信息放在pom.xml文件中可以使构建可移植。它使开发人员能够下载项目并简单地构建它们,而无需对其本地settings.xml文件进行任何进一步的修改。这种方法的问题是,当工件被释放时,相应的pom.xml文件将在其中硬编码存储库信息。如果存储库URL有变化,这些工件的消费者将由于存储库路径损坏而遇到错误。将存储库信息放在settings.xml文件中解决了这个问题,并且由于它提供的灵活性,通常在企业设置中推荐settings.xml方法。
依赖性标识
Maven依赖项通常是归档,如JAR,WAR,企业归档(EAR)和ZIP。每个Maven依赖项使用以下组,工件和版本(GAV)坐标唯一标识:
groupId:负责此项目的组织或组的标识符。示例包括org.hibernate,log4j和org.springframework.boot。
artifactId:项目生成的工件的标识符。这在使用相同groupId的项目中必须是唯一的。示例包括hibernate-tools,log4j,spring-core等。
version:表示项目的版本号。示例包括1.0.0,2.3.1-SNAPSHOT和4.3.6.Final。
type:表示生成的工件的打包。示例包括JAR,WAR和EAR。
传递依赖
在项目的pom.xml文件中声明的依赖项通常有自己的依赖项。这样的依赖关系称为传递依赖关系。以Hibernate Core为例。为了使其正常工作,它需要JBoss Logging,dom4j,javaassist等。在你的pom.xml文件中声明的Hibernate Core被认为是一个直接的依赖,诸如dom4j和javaassist之类的依赖被认为是你项目的传递依赖。 Maven的一个主要优点是它自动处理传递依赖并将它们包括在项目中。
图3-3提供了传递依赖的一个例子。注意传递依赖可以有自己的依赖。你可能想象,这可以迅速变得复杂,特别是当多个直接依赖拉不同版本的同一个JAR文件。
图3-3。传递依赖
Maven使用一种称为依赖性中介的技术来解决版本冲突。简单地说,依赖调解允许Maven拉出最接近树中项目的依赖。在图3-3中,有两个版本的依赖B:0.0.8和1.0.0。在这种情况下,版本0.0.8的依赖项B包含在项目中,因为它是一个直接依赖项并且最靠近树。现在看看依赖F的三个版本:0.1.3,1.0.0和2.2.0。所有三个依赖都在同一深度。在这种情况下,Maven将使用第一个找到的依赖项,这将是0.1.3,而不是最新的2.2.0版本。
注意虽然非常有用,但传递依赖性可能会导致问题和不可预测的副作用,因为您最终可能会包含不需要的JAR文件或旧版本的JAR文件。始终分析依赖关系树,并确保绑定所需的依赖项,并排除不需要的依赖项。
考虑一个使用JUnit进行单元测试的项目。您在项目中包含的JUnit JAR文件仅在测试期间需要。您确实不需要将JUnit JAR绑定到最终的生产归档中。同样,考虑MySQL数据库驱动程序,mysql-connector-java.jar文件。当您在容器(如Tomcat)中运行应用程序时,需要依赖关系。 Maven使用范围的概念,它允许您指定何时何地需要特定的依赖关系。
Maven提供以下六个范围:
compile:在项目构建,测试和运行的所有阶段的类路径中都提供了与编译范围的依赖关系。这是默认范围。
provided:在构建和测试阶段期间,类路径中提供了与提供的作用域的依赖关系。它们不会在生成的工件中捆绑。使用此范围的依赖关系的示例包括Servlet api,JSP api等。
runtime:在构建阶段期间,类路径中不具有运行时作用域的依赖关系。相反,它们被捆绑在生成的工件中,并在运行时可用。
test 测试:在测试阶段与测试范围的依赖关系可用。 JUnit和TestNG是测试范围的依赖的好例子。
system:与系统范围的依赖关系与提供作用域的依赖关系类似,但不从存储库检索这些依赖关系。相反,指定文件系统的硬编码路径,从中使用依赖性。
import:导入范围仅适用于.pom文件依赖项。它允许您包括来自远程.pom文件的依赖关系管理信息。导入范围仅在Maven 2.0.9或更高版本中可用。
手动依赖安装
理想情况下,您将从公共存储库或企业存储库管理器拉取项目中的依赖项。但是,有时您需要在本地存储库中提供存档,以便您可以继续开发。例如,您可能正在等待系统管理员将所需的JAR文件添加到企业存储库管理器。
Maven提供了一种方便的方式使用安装插件将存档安装到本地存储库中。清单3-2安装位于c:\ apress \ gswm-book \ chapter3文件夹中的test.jar文件。
清单3-2。手动安装依赖关系
看到BUILD SUCCESS消息后,您可以通过转到本地Maven存储库来验证安装,如图3-4所示。
总结
依赖管理是Maven的核心。 每个不平凡的Java项目都依赖于开源或外部工件,Maven的依赖关系管理自动化检索这些工件并将它们包含在构建过程的正确阶段的过程。 您还了解到Maven使用GAV坐标来识别其工件。
在下一章中,您将了解一个基本的Maven项目的组织