本指南旨在第一次为使用Maven的人员提供参考,但也打算做为一本包含公共用例的独立参考和解决方案的工具书。对于新用户,建议您按顺序浏览该材料。对于更熟悉Maven的用户,本指南致力于为手头的需求提供一个快速解决方案。如今假设您已经在本地计算机上下载了Maven并安装了Maven。若是您没有这样作,请参考下载和安装说明( Download and Installation)。html
好的,如今安装了Maven,咱们准备好了。在开始咱们的示例以前,咱们将很是简单地介绍Maven是什么,以及它如何帮助您完成平常工做和与团队成员协做。固然,Maven将为小型项目工做,可是Maven在帮助团队更有效地操做方面表现出色,它容许团队成员将精力集中在项目的涉众须要什么上。您能够将构建基础设施留给Maven!java
乍一看,Maven看起来可能有不少东西,但简而言之,Maven是一种尝试将模式应用于项目的构建基础结构,以便经过在使用最佳实践中提供清晰的路径来促进理解和生产力。Maven本质上是一个项目管理和理解工具,所以提供了一种帮助管理的方法:程序员
若是您想了解更多关于Maven的背景信息,能够查看Maven的哲学( The Philosophy of Maven)和Maven的历史( The History of Maven)。如今,让咱们继续讨论用户如何从使用Maven中获益。web
Maven能够经过使用标准约定和实践来加快开发周期,同时帮助您得到更高的效率,从而为您的构建过程提供好处。apache
如今咱们已经介绍了一些Maven的历史和目的,让咱们进入一些实际的例子,让您开始使用Maven!缓存
Maven的默认值一般是足够的,可是若是您须要更改缓存位置或使用HTTP代理,则须要建立配置。有关更多信息,请参见配置Maven指南(Guide to Configuring Maven)。服务器
咱们将直接跳到建立您的第一个Maven项目!为了建立咱们的第一个Maven项目,咱们将使用Maven的原型机制。原型(archetype )被定义为一种原始的模式或模型,全部其余同类的东西都是从这个模式或模型中制造出来的。在Maven中,原型是一个项目的模板,该模板与一些用户输入相结合,生成一个适合用户需求的Maven项目。咱们如今将向您展现原型机制是如何工做的,可是若是您想了解更多关于原型的信息,请参考咱们对原型的介绍( Introduction to Archetypes)。app
继续建立你的第一个项目!为了建立最简单的Maven项目,从命令行执行如下命令:框架
mvn -B archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DgroupId=com.mycompany.app \
-DartifactId=my-app复制代码
执行此命令后,您将注意到发生了一些事情。首先,您将注意到已经为新项目建立了一个名为my-app的目录,而且这个目录包含一个名为pom.xml
的文件,该文件应该以下所示:ssh
<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>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<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>复制代码
pom.xml
包含该项目的项目对象模型(POM)。POM是Maven中的基本工做单元。记住这一点很重要,由于Maven本质上是以项目为中心的,由于一切都围绕着项目的概念。简而言之,POM包含关于您的项目的每个重要信息,本质上是一站式消费,用于查找与您的项目相关的任何内容。理解POM很重要,鼓励新用户参考POM简介(Introduction to the POM)。
这是一个很是简单的POM,但仍然显示每一个POM包含的关键元素,所以让咱们遍历其中的每个元素,让您熟悉POM要点:
org.apache.maven.plugins
是全部Maven插件的指定groupId。 myapp-1.0.jar
)。
packaging
的默认值是JAR,所以您没必要为大多数项目指定此值。 SNAPSHOT
指示符,这代表项目处于开发状态。咱们将在本指南中讨论 snapshots的使用以及它们是如何工做的。 有关在POM中可用的元素的完整参考,请参考咱们的POM指南(POM Reference)。如今让咱们回到手头的项目。
在生成第一个项目的原型以后,您还会注意到已经建立了如下目录结构:
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)。
如今咱们有了一个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 <dir>/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中可能须要作些什么来完成一样的 事情。
如今,这只是编译一个应用程序源代码树,所显示的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] ----------------------------------------------------------------------------复制代码
一些关于输出的注意事项:
若是您只想编译测试源代码(但不想执行测试),能够执行如下操做:
mvn test-compile复制代码
既然您能够编译您的应用程序源代码,编译您的测试,并执行测试,那么您将但愿进入下一个逻辑步骤,所以您将询问...
建立JAR文件是足够直接的,能够经过执行如下命令来完成:
mvn package复制代码
若是您查看项目的POM,您将注意到packaging
元素设置为jar
。Maven知道如何从上面的命令生成一个JAR文件(稍后咱们将更多地讨论这一点)。如今您能够在${basedir}/target
目录中查看一下,您将看到生成的JAR文件。
如今,您须要在本地存储库中安装您生成的项目(JAR文件)(${user.home}/.m2/repository
是默认位置)。有关存储库的更多信息,您能够参考咱们对存储库的介绍(Introduction to Repositories),但让咱们继续安装咱们的项目!为此,请执行如下命令:
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 <dir>/my-app/target/classes
[INFO] [resources:testResources]
[INFO] [compiler:testCompile]
Compiling 1 source file to <dir>/my-app/target/test-classes
[INFO] [surefire:test]
[INFO] Setting reports dir: <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: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO] [install:install]
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to \
<local-repository>/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 )中得到更多的功能,您必须不断地添加容易出错的内容。
你还能免费获得什么?有大量的Maven插件,即便是像咱们上面这样简单的POM,也是能够开箱即用的。咱们将在这里特别提到一个,由于它是Maven的一个被高度重视的特性:在没有任何工做的状况下,这个POM有足够的信息为您的项目生成一个网站!您极可能但愿自定义Maven站点,但若是时间紧迫,则只需执行如下命令便可提供有关项目的基本信息:
mvn site复制代码
还有许多其余独立的目标也能够执行,例如:
mvn clean复制代码
这将在启动前删除包含全部生成数据的target
目录,以使其是新的。
注意,下面显示的pom.xml
文件中version标记的值有后缀:-SNAPSHOT
。
<project xmlns="http://maven.apache.org/POM/4.0.0"
...
<groupId>...</groupId>
<artifactId>my-app</artifactId>
...
<version>1.0-SNAPSHOT</version>
<name>Maven Quick Start Archetype</name>
...复制代码
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中同样简单:
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
...复制代码
您会注意到,Maven中的全部插件看起来都很像一个依赖项-并且在某些方面它们是依赖的。这个插件将被自动下载和使用-若是你要求的话包括一个特定的版本(默认的是使用最新的可用版本)。
configuration
元素将给定的参数应用于编译器插件中的每一个目标。在上面的例子中,编译器插件已经被用做构建过程的一部分,这只是改变了配置。还能够向流程中添加新的目标,并配置特定的目标。有关这方面的信息,请参阅构建生命周期介绍(Introduction to the Build Lifecycle)。
要了解插件的配置,您能够看到插件列表(Plugins List)并导航到您正在使用的插件和目标。有关如何配置插件可用参数的通常信息,请参阅配置插件指南(Guide to Configuring Plugins)。
另外一个能够知足的常见用例是将资源打包到JAR文件中,它不须要对上面的POM进行更改。对于这个常见的任务,Maven再次依赖于 Standard Directory Layout,这意味着经过使用标准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中定义的值之1、在用户的setings.xml中定义的值、在外部属性文件中定义的属性或系统属性。
若要在复制时让Maven筛选资源,只需在你的pom.xml
中将资源目录的filtering
设置为true:
<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>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>复制代码
您会注意到,咱们必须添加之前没有的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中添加对这个新文件的引用:
<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>
<build>
<filters>
<filter>src/main/filters/filter.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>复制代码
而后,若是咱们在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
的引用):
<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>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<my.filter.value>hello</my.filter.value>
</properties>
</project>复制代码
过滤资源也能够从系统属性中得到值;要么是内置到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)。
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
这样的值。有关能够为依赖项指定的全部内容的详细信息,请参阅项目描述符指南(Project Descriptor Reference)。
有关整个依赖机制的更多信息,请参见依赖机制介绍(Introduction to Dependency Mechanism)。
有了这些关于依赖项的信息,Maven将可以在构建项目时引用该依赖项。Maven从哪里引用依赖项?Maven在本地存储库中查找全部依赖项(${user.home}/.m2/repository
是默认位置)。在上一节中,咱们将项目(My-app-1.0-SNAPSHOT.jar)安装到本地存储库中。一旦安装在那里,另外一个项目就能够将该jar引用为依赖项,只需将依赖信息添加到它的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">
<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下载了不少东西(这些下载是用于构建项目的各类插件的依赖项)。默认状况下,能够在http://repo.maven.apache.org/maven2/上找到(并浏览)Maven使用的远程存储库。您还能够设置本身的远程存储库(多是您公司的中央存储库)来代替默认远程存储库或除了默认远程存储库以外使用。有关存储库的更多信息,请参阅存储库介绍(Introduction to Repositorie)。
让咱们将另外一个依赖项添加到咱们的项目中。假设咱们在代码中添加了一些日志,而且须要将log4j做为依赖项添加。首先,咱们须要知道log4j的groupId、artifactId和version是什么。Maven Central上的适当目录名为/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>复制代码
从这个文件中,咱们能够看到咱们想要的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文件中了:
<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依赖项。
要将JAR部署到外部存储库,您必须在pom.xml中配置存储库url,并在settings.xml中配置链接到存储库的身份验证信息。
下面是一个使用scp和用户名/密码身份验证的示例:
<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>org.apache.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<filters>
<filter>src/main/filters/filters.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<!--
|
|
|
-->
<distributionManagement>
<repository>
<id>mycompany-repository</id>
<name>MyCompany Repository</name>
<url>scp://repository.mycompany.com/repository/maven2</url>
</repository>
</distributionManagement>
</project>复制代码
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<servers>
<server>
<id>mycompany-repository</id>
<username>jvanzyl</username>
<!-- Default value is ~/.ssh/id_dsa -->
<privateKey>/path/to/identity</privateKey> (default is ~/.ssh/id_dsa)
<passphrase>my_key_passphrase</passphrase>
</server>
</servers>
...
</settings>复制代码
请注意,若是链接到openssh ssh服务器,该服务器的参数“PasswordAuthentication”在sshd_conf中设置为“no”,则每次输入用户名/密码身份验证时都必须键入密码(尽管您可使用另外一个ssh客户机登陆,输入用户名和密码)。在这种状况下,您可能但愿切换到公钥身份验证。
在settings.xml
中使用密码时应该当心。有关更多信息,请参见密码加密(Password Encryption)。
为了让您从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),学习如何为您的项目建立文档。
注意,生命周期适用于任何项目类型。例如,回到基本目录中,咱们能够建立一个简单的web应用程序:
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DgroupId=com.mycompany.app \
-DartifactId=my-webapp复制代码
请注意,全部这些都必须在一行上。这将建立一个名为my-webapp
的目录,其中包含如下项目描述符:
<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-webapp</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>my-webapp</finalName>
</build>
</project>复制代码
注意
元素-这告诉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文件应该包含如下内容:
<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>app</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>my-app</module>
<module>my-webapp</module>
</modules>
</project>复制代码
咱们须要一个来自webapp的JAR依赖项,因此将其添加到my-webapp/pom.xml
中:
...
<dependencies>
<dependency>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
...
</dependencies>复制代码
最后,将如下
元素添加到子目录中的两个其余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">
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>app</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
...复制代码
如今试试.。在顶层目录中,运行:
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中结束。缘由是
元素-它只是测试所必需的,所以不包括在web应用程序中,由于编译时依赖于my-app
。
最后一步是包含父定义。这与您可能熟悉的Maven 1.0中的extend
元素不一样:这能够确保POM始终能够被定位,即便经过在存储库中查找该项目,该项目也是独立于其父项目的。