Maven入门指南

半城伤御伤魂 提交于 2019-12-01 19:24:39
# Maven入门指南 本指南旨在第一次为使用Maven的人员提供参考,但也打算作为一本包含公共用例的独立参考和解决方案的工具书。对于新用户,建议您按顺序浏览该材料。对于更熟悉Maven的用户,本指南致力于为手头的需求提供一个快速解决方案。现在假设您已经在本地计算机上下载了Maven并安装了Maven。如果您没有这样做,请参考下载和安装说明( [Download and Installation](http://maven.apache.org/download.html))。 好的,现在安装了Maven,我们准备好了。在开始我们的示例之前,我们将非常简单地介绍Maven是什么,以及它如何帮助您完成日常工作和与团队成员协作。当然,Maven将为小型项目工作,但是Maven在帮助团队更有效地操作方面表现出色,它允许团队成员将精力集中在项目的涉众需要什么上。您可以将构建基础设施留给Maven! ### Maven是什么? 乍一看,Maven看起来可能有很多东西,但简而言之,Maven是一种尝试将模式应用于项目的构建基础结构,以便通过在使用最佳实践中提供清晰的路径来促进理解和生产力。Maven本质上是一个项目管理和理解工具,因此提供了一种帮助管理的方法: - 构建 - 文档 - 报告 - 依赖 - SCMs - 版本 - 发布 如果您想了解更多关于Maven的背景信息,可以查看Maven的哲学( [The Philosophy of Maven](http://maven.apache.org/background/philosophy-of-maven.html))和Maven的历史( [The History of Maven](http://maven.apache.org/background/history-of-maven.html))。现在,让我们继续讨论用户如何从使用Maven中获益。 ### Maven如何使我的开发过程受益? Maven可以通过使用标准约定和实践来加快开发周期,同时帮助您获得更高的效率,从而为您的构建过程提供好处。 现在我们已经介绍了一些Maven的历史和目的,让我们进入一些实际的例子,让您开始使用Maven! ### 如何配置Maven? Maven的默认值通常是足够的,但是如果您需要更改缓存位置或使用HTTP代理,则需要创建配置。有关更多信息,请参见配置Maven指南([Guide to Configuring Maven](http://maven.apache.org/guides/mini/guide-configuring-maven.html))。 ### 如何进行我的第一个Maven项目? 我们将直接跳到创建您的第一个Maven项目!为了创建我们的第一个Maven项目,我们将使用Maven的原型机制。原型(archetype )被定义为一种原始的模式或模型,所有其他同类的东西都是从这个模式或模型中制造出来的。在Maven中,原型是一个项目的模板,该模板与一些用户输入相结合,生成一个适合用户需求的Maven项目。我们现在将向您展示原型机制是如何工作的,但是如果您想了解更多关于原型的信息,请参考我们对原型的介绍( [Introduction to Archetypes](http://maven.apache.org/guides/introduction/introduction-to-archetypes.html))。 继续创建你的第一个项目!为了创建最简单的Maven项目,从命令行执行以下命令: ``` mvn -B archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DgroupId=com.mycompany.app \ -DartifactId=my-app ``` 执行此命令后,您将注意到发生了一些事情。首先,您将注意到已经为新项目创建了一个名为my-app的目录,并且这个目录包含一个名为`pom.xml`的文件,该文件应该如下所示: ```xml 4.0.0com.mycompany.appmy-appjar1.0-SNAPSHOTMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11test ``` `pom.xml`包含该项目的项目对象模型(POM)。POM是Maven中的基本工作单元。记住这一点很重要,因为Maven本质上是以项目为中心的,因为一切都围绕着项目的概念。简而言之,POM包含关于您的项目的每一个重要信息,本质上是一站式消费,用于查找与您的项目相关的任何内容。理解POM很重要,鼓励新用户参考POM简介([Introduction to the POM](http://maven.apache.org/guides/introduction/introduction-to-the-pom.html))。 这是一个非常简单的POM,但仍然显示每个POM包含的关键元素,因此让我们遍历其中的每一个元素,让您熟悉POM要点: - **project** 这是所有Maven pom.xml文件中的顶级元素。 - **modelVersion** 此元素指示POM使用的对象模型的版本。模型本身的版本变化非常少,但如果Maven开发人员认为有必要更改模型,则必须这样做,以确保使用的稳定性。 - **groupId** 此元素指示创建项目的组织或组的唯一标识符。groupId是项目的关键标识符之一,通常基于组织的完全限定域名。例如,`org.apache.maven.plugins`是所有Maven插件的指定groupId。 - **artifactId** 此元素指示由此项目生成的项目的唯一名称。项目的主要框架通常是JAR文件。像源包这样的次要构件也使用artifactId作为其最终名称的一部分。Maven生成的典型框架将具有-.表单(例如`myapp-1.0.jar`)。 - **packaging** 此元素指示此项目将使用的包类型(例如JAR、WAR、EAR等)。这不仅意味着产生的项目是JAR、WAR或EAR,而且还可以指示要作为构建过程的一部分使用的特定生命周期。(生命周期是我们将在指南中进一步讨论的一个主题。现在,请记住,项目的指定打包可以在定制构建生命周期中发挥作用。)`packaging`的默认值是JAR,因此您不必为大多数项目指定此值。 - **version** 此元素指示项目生成的版本。Maven对帮助您进行版本管理有很大帮助,您经常会看到版本中的`SNAPSHOT`指示符,这表明项目处于开发状态。我们将在本指南中讨论 [snapshots](http://maven.apache.org/guides/getting-started/index.html#What_is_a_SNAPSHOT_version)的使用以及它们是如何工作的。 - **name** 此元素指示用于项目的显示名称。这经常用于Maven生成的文档中。 - **url** 此元素指示在何处可以找到项目的站点。这经常用于Maven生成的文档中。 - **description** 此元素提供了项目的基本说明。这经常用于Maven生成的文档中。 有关在POM中可用的元素的完整参考,请参考我们的POM指南([POM Reference](http://maven.apache.org/ref/current/maven-model/maven.html))。现在让我们回到手头的项目。 在生成第一个项目的原型之后,您还会注意到已经创建了以下目录结构: ``` my-app |-- pom.xml `-- src |-- main | `-- java | `-- com | `-- mycompany | `-- app | `-- App.java `-- test `-- java `-- com `-- mycompany `-- app `-- AppTest.java ``` 如您所见,从原型(archetype)创建的项目有一个POM、一个用于应用程序源的源代码树和一个用于测试源的源代码树。这是Maven项目的标准布局(应用程序源位于`${basedir}/src/main/java`,测试源位于`${basedir}/src/test/java`中,其中${basedir}表示包含`pom.xml`的目录)。 如果要手工创建Maven项目,我们建议使用这个目录结构。这是一个Maven约定,要了解更多有关它的信息,您可以阅读我们对标准目录布局的介绍([Introduction to the Standard Directory Layout](http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html))。 现在我们有了一个POM、一些应用程序源代码和一些您可能需要的测试源代码。 ### 如何编译我的应用程序源代码? 通过archetype:generate切换到被创建pom.xml的目录并执行以下命令来编译应用程序源代码: ``` mvn compile ``` 在执行此命令时,您应该看到输出如下所示: ``` [INFO] ---------------------------------------------------------------------------- [INFO] Building Maven Quick Start Archetype [INFO] task-segment: [compile] [INFO] ---------------------------------------------------------------------------- [INFO] artifact org.apache.maven.plugins:maven-resources-plugin: \ checking for updates from central ... [INFO] artifact org.apache.maven.plugins:maven-compiler-plugin: \ checking for updates from central ... [INFO] [resources:resources] ... [INFO] [compiler:compile] Compiling 1 source file to /my-app/target/classes [INFO] ---------------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] ---------------------------------------------------------------------------- [INFO] Total time: 3 minutes 54 seconds [INFO] Finished at: Fri Sep 23 15:48:34 GMT-05:00 2005 [INFO] Final Memory: 2M/6M [INFO] ---------------------------------------------------------------------------- ``` 当您第一次执行此命令(或任何其他命令)时,Maven将需要下载完成该命令所需的所有插件和相关依赖项。从Maven的干净安装来看,这可能需要相当长的时间(在上面的输出中,花费了将近4分钟)。如果您再次执行该命令,Maven现在将得到它所需的东西,因此它不需要下载任何新的内容,并且能够更快地执行该命令。 从输出中可以看到,编译后的类被放置在`${basedir}/target/classes`中,这是Maven使用的另一个标准约定。因此,如果您是一个敏锐的观察者,您会注意到通过使用标准约定,上面的POM非常小,并且您不必明确地告诉Maven您的源代码在哪里或输出应该去哪里。通过遵循标准的Maven约定,您可以在很小的努力下完成很多事情!作为一个偶然的比较,让我们来看看您在 [Ant](http://ant.apache.org/)中可能需要做些什么来完成同样的 [事情](http://maven.apache.org/ant/build-a1.xml)。 现在,这只是编译一个应用程序源代码树,所显示的Ant脚本与上面显示的POM大小基本相同。但是,我们将看到,我们还可以做更多的只是简单的POM! ### 如何编译测试源代码并运行单元测试? 现在您正在成功地编译您的应用程序的源代码,现在您已经获得了一些您想要编译和执行的单元测试(因为每个程序员总是编写和执行他们的单元测试*轻推眨眼*)。 执行以下命令: ``` mvn test ``` 在执行此命令时,您应该看到输出如下所示: ``` [INFO] ---------------------------------------------------------------------------- [INFO] Building Maven Quick Start Archetype [INFO] task-segment: [test] [INFO] ---------------------------------------------------------------------------- [INFO] artifact org.apache.maven.plugins:maven-surefire-plugin: \ checking for updates from central ... [INFO] [resources:resources] [INFO] [compiler:compile] [INFO] Nothing to compile - all classes are up to date [INFO] [resources:testResources] [INFO] [compiler:testCompile] Compiling 1 source file to C:\Test\Maven2\test\my-app\target\test-classes ... [INFO] [surefire:test] [INFO] Setting reports dir: C:\Test\Maven2\test\my-app\target/surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- [surefire] Running com.mycompany.app.AppTest [surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0 sec Results : [surefire] Tests run: 1, Failures: 0, Errors: 0 [INFO] ---------------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] ---------------------------------------------------------------------------- [INFO] Total time: 15 seconds [INFO] Finished at: Thu Oct 06 08:12:17 MDT 2005 [INFO] Final Memory: 2M/8M [INFO] ---------------------------------------------------------------------------- ``` 一些关于输出的注意事项: - Maven这次下载更多的依赖项。这些是执行测试所必需的依赖项和插件(它已经拥有编译所需的依赖项,不会再下载它们)。 - 在编译和执行测试之前,Maven编译主代码(所有这些类都是最新的,因为我们自上次编译以来什么都没有改变)。 如果您只想编译测试源代码(但不想执行测试),可以执行以下操作: ``` mvn test-compile ``` 既然您可以编译您的应用程序源代码,编译您的测试,并执行测试,那么您将希望进入下一个逻辑步骤,因此您将询问... ### 如何创建JAR并将其安装在本地存储库中? 创建JAR文件是足够直接的,可以通过执行以下命令来完成: ``` mvn package ``` 如果您查看项目的POM,您将注意到`packaging`元素设置为`jar`。Maven知道如何从上面的命令生成一个JAR文件(稍后我们将更多地讨论这一点)。现在您可以在`${basedir}/target`目录中查看一下,您将看到生成的JAR文件。 现在,您需要在本地存储库中安装您生成的项目(JAR文件)(`${user.home}/.m2/repository`是默认位置)。有关存储库的更多信息,您可以参考我们对存储库的介绍([Introduction to Repositories](http://maven.apache.org/guides/introduction/introduction-to-repositories.html)),但让我们继续安装我们的项目!为此,请执行以下命令: ``` mvn install ``` 在执行此命令时,您将看到以下输出: ``` [INFO] ---------------------------------------------------------------------------- [INFO] Building Maven Quick Start Archetype [INFO] task-segment: [install] [INFO] ---------------------------------------------------------------------------- [INFO] [resources:resources] [INFO] [compiler:compile] Compiling 1 source file to /my-app/target/classes [INFO] [resources:testResources] [INFO] [compiler:testCompile] Compiling 1 source file to /my-app/target/test-classes [INFO] [surefire:test] [INFO] Setting reports dir: /my-app/target/surefire-reports ------------------------------------------------------- T E S T S ------------------------------------------------------- [surefire] Running com.mycompany.app.AppTest [surefire] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec Results : [surefire] Tests run: 1, Failures: 0, Errors: 0 [INFO] [jar:jar] [INFO] Building jar: /my-app/target/my-app-1.0-SNAPSHOT.jar [INFO] [install:install] [INFO] Installing /my-app/target/my-app-1.0-SNAPSHOT.jar to \ /com/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar [INFO] ---------------------------------------------------------------------------- [INFO] BUILD SUCCESSFUL [INFO] ---------------------------------------------------------------------------- [INFO] Total time: 5 seconds [INFO] Finished at: Tue Oct 04 13:20:32 GMT-05:00 2005 [INFO] Final Memory: 3M/8M [INFO] ---------------------------------------------------------------------------- ``` 注意,强制插件(它执行测试)查找包含在具有特定命名约定的文件中的测试。默认情况下,包括的测试如下: - `**/*Test.java` - `**/Test*.java` - `**/*TestCase.java` 默认情况排除如下: - `**/Abstract*Test.java` - `**/Abstract*TestCase.java` 您已经完成了设置、构建、测试、打包和安装典型Maven项目的过程。这可能是项目使用Maven所做的绝大部分工作,如果您已经注意到,到目前为止所能做的一切都是由一个18行文件驱动的,即项目的模型或POM。如果您查看一个典型的Ant构建文件,它提供了与我们迄今为止所实现的功能相同的功能,您会注意到它的大小已经是POM的两倍,而且我们才刚刚开始!您可以从Maven获得更多的功能,而不需要对我们目前的POM进行任何添加。要从我们的示例Ant构建文件( [build file](http://maven.apache.org/ant/build-a1.xml) )中获得更多的功能,您必须不断地添加容易出错的内容。 你还能免费得到什么?有大量的Maven插件,即使是像我们上面这样简单的POM,也是可以开箱即用的。我们将在这里特别提到一个,因为它是Maven的一个被高度重视的特性:在没有任何工作的情况下,这个POM有足够的信息为您的项目生成一个网站!您很可能希望自定义Maven站点,但如果时间紧迫,则只需执行以下命令即可提供有关项目的基本信息: ``` mvn site ``` 还有许多其他独立的目标也可以执行,例如: ``` mvn clean ``` 这将在启动前删除包含所有生成数据的`target`目录,以使其是新的。 ### 什么是SNAPSHOT版本? 注意,下面显示的`pom.xml`文件中**version**标记的值有后缀:`-SNAPSHOT`。 ``` ... my-app ... 1.0-SNAPSHOTMaven Quick Start Archetype ... ``` `SNAPSHOT`是指开发分支的“最新”代码,并不保证代码是稳定的或不变的。相反,'release' 中的代码(任何没有后缀`SNAPSHOT`的版本值)都是不变的。 换句话说,SNAPSHOT版本是最后的 'release' 版本之前的“开发”版本。SNAPSHOT比它的'release' 版“旧”。 在发布过程中,**x.y-SNAPSHOT**的版本更改为**x.y**。发布过程中还将开发版本增加到 **x.(y+1)-SNAPSHOT**。例如,**1.0-SNAPSHOT**作为1.0版发布,新的开发版本为**1.1-SNAPSHOT**。 ### 如何使用插件? 每当您想要自定义Maven项目的构建时,都是通过添加或重新配置插件来完成的。 **注意,对于Maven 1.0用户:**在Maven 1.0中,您应该将一些`preGoal`添加到`maven.xml`中,并将一些条目添加到`project.properties`中。在这里,有点不同。对于本例,我们将配置Java编译器以允许JDK5.0源代码。这就像将其添加到POM中一样简单: ```xml ... org.apache.maven.pluginsmaven-compiler-plugin3.31.51.5 ... ``` 您会注意到,Maven中的所有插件看起来都很像一个依赖项-而且在某些方面它们是依赖的。这个插件将被自动下载和使用-如果你要求的话包括一个特定的版本(默认的是使用最新的可用版本)。 `configuration`元素将给定的参数应用于编译器插件中的每个目标。在上面的例子中,编译器插件已经被用作构建过程的一部分,这只是改变了配置。还可以向流程中添加新的目标,并配置特定的目标。有关这方面的信息,请参阅构建生命周期介绍([Introduction to the Build Lifecycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html))。 要了解插件的配置,您可以看到插件列表([Plugins List](http://maven.apache.org/plugins/))并导航到您正在使用的插件和目标。有关如何配置插件可用参数的一般信息,请参阅配置插件指南([Guide to Configuring Plugins](http://maven.apache.org/guides/mini/guide-configuring-plugins.html))。 ### 如何将资源添加到我的JAR中? 另一个可以满足的常见用例是将资源打包到JAR文件中,它不需要对上面的POM进行更改。对于这个常见的任务,Maven再次依赖于 [Standard Directory Layout](http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html),这意味着通过使用标准Maven约定,您可以将资源打包到JAR中,只需将这些资源放在标准目录结构中即可。 您可以在下面的示例中看到,我们添加了目录`${basedir}/src/main/resources`,我们希望将任何资源打包到JAR中。Maven使用的简单规则是:`${basedir}/src/main/resources`目录中的任何目录或文件都打包在JAR中,其结构与JAR底部的结构完全相同。 ``` my-app |-- pom.xml `-- src |-- main | |-- java | | `-- com | | `-- mycompany | | `-- app | | `-- App.java | `-- resources | `-- META-INF | `-- application.properties `-- test `-- java `-- com `-- mycompany `-- app `-- AppTest.java ``` 因此,在我们的示例中可以看到,我们在该目录中有一个`META-INF`目录和一个`application.properties`文件。如果您打开Maven为您创建的JAR并查看它,您将看到以下内容: ``` |-- META-INF | |-- MANIFEST.MF | |-- application.properties | `-- maven | `-- com.mycompany.app | `-- my-app | |-- pom.properties | `-- pom.xml `-- com `-- mycompany `-- app `-- App.class ``` 如您所见,`${basedir}/src/main/resources`的内容可以从JAR的里边找到,而`application.properties`文件位于`META-INF`目录中。您还会注意到一些其他文件,如`META-INF/MANIFEST.MF`,以及`pom.xml`和`pom.properties`文件。这些都是标准的,在Maven中生成一个JAR。如果选择,可以创建自己的清单,但如果不选择,Maven将默认生成清单。(还可以修改默认清单中的条目。我们稍后再谈这个问题。) `pom.xml`和`pom.properties`文件打包在JAR中,这样由Maven生成的每个项目都是自描述的,并允许您在需要时在自己的应用程序中使用元数据。一个简单的用途可能是检索应用程序的版本。对POM文件的操作将要求您使用一些Maven实用程序,但是可以使用标准的Java API来使用这些属性,如下所示: ``` #Generated by Maven #Tue Oct 04 15:43:21 GMT-05:00 2005 version=1.0-SNAPSHOT groupId=com.mycompany.app artifactId=my-app ``` 要将资源(resources)添加到单元测试的类路径中,您可以遵循与将资源添加到JAR中相同的模式,但将资源放在其中的目录是${basedir}/src/test/resources。此时,您将拥有一个类似于以下内容的项目目录结构: ``` my-app |-- pom.xml `-- src |-- main | |-- java | | `-- com | | `-- mycompany | | `-- app | | `-- App.java | `-- resources | `-- META-INF | |-- application.properties `-- test |-- java | `-- com | `-- mycompany | `-- app | `-- AppTest.java `-- resources `-- test.properties ``` 在单元测试中,您可以使用以下代码片段来访问测试所需的资源: ``` ... // Retrieve resource InputStream is = getClass().getResourceAsStream( "/test.properties" ); // Do something with the resource ... ``` ### 如何过滤资源文件? 有时,资源文件需要包含只能在构建时提供的值。要在Maven中实现这一点,请使用语法`${}`将包含该值的属性引用到您的资源文件中。该属性可以是在pom.xml中定义的值之一、在用户的setings.xml中定义的值、在外部属性文件中定义的属性或系统属性。 若要在复制时让Maven筛选资源,只需在你的`pom.xml`中将资源目录的`filtering`设置为true: ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11testsrc/main/resourcestrue ``` 您会注意到,我们必须添加以前没有的`build`、`resources`和`resource`元素。此外,我们还必须明确声明资源位于src/main/resources目录中。所有这些信息以前都是以默认值的形式提供的,但是由于`filtering`的默认值为false,所以我们必须将其添加到pom.xml中,以便覆盖该默认值并将`filtering`设置为true。 要引用pom.xml中定义的属性,属性名称使用定义值的XML元素的名称,并允许“pom”作为项目(Root)元素的别名。所以`${project.name}`是指项目的名称,`${project.version}`是指项目的版本,`${project.build.finalName}`是指在打包构建项目时创建的文件的最终名称,等等。类似地,可以使用以“settings”开头的属性名称引用用户`Setings.xml`中的值(例如,`${setings.localRepository}`引用用户本地存储库的路径)。 为了继续我们的示例,让我们将两个属性添加到`application.properties`文件(我们将其放在`src/main/resources`目录中),当资源被过滤时,它的值将被提供: ``` # application.properties application.name=${project.name} application.version=${project.version} ``` 这样,您就可以执行以下命令(Process-Resources是复制和过滤资源的构建生命周期阶段): ``` mvn process-resources ``` target/classes下的`application.properties`文件(最终将进入JAR)如下所示: ``` # application.properties application.name=Maven Quick Start Archetype application.version=1.0-SNAPSHOT ``` 若要引用在外部文件中定义的属性,只需将对该外部文件的引用添加到pom.xml文件中即可。首先,让我们创建外部属性文件,并将其命名为`src/main/filters/filter.properties`: ``` # filter.properties my.filter.value=hello! ``` 接下来,我们将在pom.xml中添加对这个新文件的引用: ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11testsrc/main/filters/filter.propertiessrc/main/resourcestrue ``` 然后,如果我们在`application.properties`文件中添加对此属性的引用: ``` # application.properties application.name=${project.name} application.version=${project.version} message=${my.filter.value} ``` 下次执行`mvn process-resources`命令时,我们将把新的属性值放入`application.properties`中。作为在外部文件中定义my.filter.value属性的一种替代方法,您也可以在`pom.xml`的`properties`节点中定义它,并获得同样的效果(请注意,我也不需要对`src/main/filters/filter.properties`的引用): ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11testsrc/main/resourcestruehello ``` 过滤资源也可以从系统属性中获得值;要么是内置到Java中的系统属性(比如`java.version`或`user.home`),要么是使用标准Java-D参数在命令行上定义的属性。为了继续这个示例,让我们将`application.properties`文件更改为如下所示: ``` # application.properties java.version=${java.version} command.line.prop=${command.line.prop} ``` 现在,当您执行以下命令(请注意命令行上的command.line.prop属性的定义)时,`application.properties`文件将包含来自系统属性的值。 ``` mvn process-resources "-Dcommand.line.prop=hello again" ``` ### 如何使用外部依赖项? 您可能已经注意到我们作为示例使用的POM中的`dependencies`元素。事实上,您一直在使用外部依赖项,但是这里我们将更详细地讨论这一点。关于更详细的介绍,请参阅我们对依赖机制的介绍( [Introduction to Dependency Mechanism](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html))。 pom.xml的`dependencies`节点列出了我们的项目构建所需的所有外部依赖项(无论是在编译时、测试时、运行时还是其他什么时候都需要该依赖项)。现在,我们的项目只依赖于JUnit(为了清晰起见,我取出了所有的资源过滤工具): ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11test ``` 对于每个外部依赖项,您至少需要定义4件事情:groupId, artifactId, version 和 scope。groupId、artifactId和version与构建该依赖项的`pom.xml`中提供的相同。scope元素指示项目如何使用该依赖项,并且可以是像`compile`, `test`和 `runtime`这样的值。有关可以为依赖项指定的所有内容的详细信息,请参阅项目描述符指南([Project Descriptor Reference](http://maven.apache.org/ref/current/maven-model/maven.html))。 有关整个依赖机制的更多信息,请参见依赖机制介绍([Introduction to Dependency Mechanism](http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html))。 有了这些关于依赖项的信息,Maven将能够在构建项目时引用该依赖项。Maven从哪里引用依赖项?Maven在本地存储库中查找所有依赖项(`${user.home}/.m2/repository`是默认位置)。在上一节中,我们将项目(My-app-1.0-SNAPSHOT.jar)安装到本地存储库中。一旦安装在那里,另一个项目就可以将该jar引用为依赖项,只需将依赖信息添加到它的pom.xml中: ```xml com.mycompany.appmy-other-app ... ... com.mycompany.appmy-app1.0-SNAPSHOTcompile ``` 其他地方构建的依赖关系呢?他们怎么进入我的本地存储库?每当项目引用本地存储库中不可用的依赖项时,Maven将依赖项从远程存储库下载到本地存储库中。在构建第一个项目时,您可能注意到Maven下载了很多东西(这些下载是用于构建项目的各种插件的依赖项)。默认情况下,可以在http://repo.maven.apache.org/maven2/上找到(并浏览)Maven使用的远程存储库。您还可以设置自己的远程存储库(可能是您公司的中央存储库)来代替默认远程存储库或除了默认远程存储库之外使用。有关存储库的更多信息,请参阅存储库介绍([Introduction to Repositorie](http://maven.apache.org/guides/introduction/introduction-to-repositories.html))。 让我们将另一个依赖项添加到我们的项目中。假设我们在代码中添加了一些日志,并且需要将log4j作为依赖项添加。首先,我们需要知道log4j的groupId、artifactId和version是什么。Maven Central上的适当目录名为/maven2/log4j/log4j。该目录中有一个名为maven-metadata.xml的文件。下面是log4j的maven-metadata.xml如下所示: ```xml log4jlog4j1.1.31.1.31.2.41.2.51.2.61.2.71.2.81.2.111.2.91.2.12 ``` 从这个文件中,我们可以看到我们想要的groupId是“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文件中了: ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11testlog4jlog4j1.2.12compile ``` 现在,当我们编译项目(`mvn compile`)时,我们将看到Maven为我们下载log4j依赖项。 ### 如何在远程存储库中部署JAR? 要将JAR部署到外部存储库,您必须在pom.xml中配置存储库url,并在settings.xml中配置连接到存储库的身份验证信息。 下面是一个使用scp和用户名/密码身份验证的示例: ```xml 4.0.0com.mycompany.appmy-app1.0-SNAPSHOTjarMaven Quick Start Archetypehttp://maven.apache.orgjunitjunit4.11testorg.apache.codehaus.plexusplexus-utils1.0.4src/main/filters/filters.propertiessrc/main/resourcestruemycompany-repositoryMyCompany Repositoryscp://repository.mycompany.com/repository/maven2 ``` ```xml ... mycompany-repositoryjvanzyl/path/to/identity (default is ~/.ssh/id_dsa) my_key_passphrase ... ``` 请注意,如果连接到openssh ssh服务器,该服务器的参数“PasswordAuthentication”在sshd_conf中设置为“no”,则每次输入用户名/密码身份验证时都必须键入密码(尽管您可以使用另一个ssh客户机登录,输入用户名和密码)。在这种情况下,您可能希望切换到公钥身份验证。 在`settings.xml`中使用密码时应该小心。有关更多信息,请参见密码加密([Password Encryption](http://maven.apache.org/guides/mini/guide-encryption.html))。 ### 如何创建文档? 为了让您从Maven的文档系统开始,您可以使用原型机制为现有项目生成一个站点,使用以下命令: ``` mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-site \ -DgroupId=com.mycompany.app \ -DartifactId=my-app-site ``` 现在转到指南中去创建一个站点([Guide to creating a site](http://maven.apache.org/guides/mini/guide-site.html)),学习如何为您的项目创建文档。 ### 如何构建其他类型的项目? 注意,生命周期适用于任何项目类型。例如,回到基本目录中,我们可以创建一个简单的web应用程序: ``` mvn archetype:generate \ -DarchetypeGroupId=org.apache.maven.archetypes \ -DarchetypeArtifactId=maven-archetype-webapp \ -DgroupId=com.mycompany.app \ -DartifactId=my-webapp ``` 请注意,所有这些都必须在一行上。这将创建一个名为`my-webapp`的目录,其中包含以下项目描述符: ```xml 4.0.0com.mycompany.appmy-webapp1.0-SNAPSHOTwarjunitjunit4.11testmy-webapp ``` 注意``元素-这告诉Maven构建为WAR。切换到webapp项目的目录并尝试: ``` mvn package ``` 您将看到构建了`target/my-webapp.war`,并且执行了所有正常步骤。 ### 如何同时构建多个项目? Maven内置了处理多个模块的概念。在本节中,我们将展示如何构建上面的WAR,并在一个步骤中包含前面的JAR。 首先,我们需要在其他两个目录中添加一个父`pom.xml`文件,因此它应该如下所示: ``` +- pom.xml +- my-app | +- pom.xml | +- src | +- main | +- java +- my-webapp | +- pom.xml | +- src | +- main | +- webapp ``` 您将要创建的POM文件应该包含以下内容: ```xml 4.0.0com.mycompany.appapp1.0-SNAPSHOTpommy-appmy-webapp ``` 我们需要一个来自webapp的JAR依赖项,所以将其添加到`my-webapp/pom.xml`中: ```xml ... com.mycompany.appmy-app1.0-SNAPSHOT ... ``` 最后,将以下``元素添加到子目录中的两个其他`pom.xml`文件中: ```xml com.mycompany.appapp1.0-SNAPSHOT ... ``` 现在试试.。在顶层目录中,运行: ``` mvn verify ``` WAR现在已经在`my-webapp/target/my-webapp.war`中创建,并且JAR被包括在内: ``` $ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war 0 Fri Jun 24 10:59:56 EST 2005 META-INF/ 222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF 0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/ 0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/ 0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/ 3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml 0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/ 215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml 123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.properties 52 Fri Jun 24 10:59:56 EST 2005 index.jsp 0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/ 2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar ``` 这是怎么回事?首先,创建的父POM(称为`app`)具有`POM`的打包和定义的模块列表。这告诉Maven在项目集上运行所有操作,而不是只运行当前的操作(要覆盖这种行为,可以使用`--non-recursive`命令行选项)。 接下来,我们告诉WAR,它需要`my-app` JAR。这做了几件事:它使它可以在类路径上访问WAR中的任何代码(在本例中没有),它确保JAR总是在WAR之前构建的,并且它指示WAR插件将JAR包含在其库目录中。 您可能已经注意到`junit-4.11.jar`是一种依赖关系,但没有在WAR中结束。原因是`test`元素-它只是测试所必需的,因此不包括在web应用程序中,因为编译时依赖于`my-app`。 最后一步是包含父定义。这与您可能熟悉的Maven 1.0中的`extend`元素不同:这可以确保POM始终可以被定位,即使通过在存储库中查找该项目,该项目也是独立于其父项目的。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!