Apache Maven --- [Maven入门指南]

本指南的目的是为初次使用Maven的人提供一个参考,但同时也做为一个独立参考和解决方案的食谱来为常见用例提供服务.对于第一次使用的用户来讲,建议按顺序依次浏览指南.而对于更加熟悉Maven的用户来讲,本指南尽力提供一个急需的快速解决方案.咱们假设你已经下载并成功安装了Maven,若是没有,请先查阅下载和安装说明.html

好了,因此如今你已经安装了Maven,准备出发.在咱们进入咱们的示例以前,咱们先来简单的过一遍Maven是什么,它如何帮助你的平常工做以及团队之间的协做.固然Maven能够为小项目工做,可是它的亮点是可以经过容许团队人员关注于项目利益者的需求来帮助团队更有效率的运做.你能够把构建基础委托给Maven.java

什么是Mavenweb

乍一看Maven能够是不少东西,可是简而言之,它是为了促进理解和生产,经过提供一个清晰的最优使用实践的步骤来视图将模式应用到项目的构建当中.它是一个项目综合管理工具,提供了一种方法来帮助管理:apache

构建缓存

文档服务器

报告app

依赖eclipse

SCMs(供应链?)ssh

发布webapp

分发

Maven如何让个人开发过程受益

Maven经过采用标准规范和实践来促进你的开发周期并同时帮助你取得更高的成功.

我如何设置Maven

Maven的默认配置一般是足够使用的,可是若是你想要改变本地缓存或者绑定HTTP代理,你须要建立配置.具体查阅Maven配置指南.

我如何开始个人第一个Maven项目

咱们将使用Maven的原型机制来建立咱们的第一个Maven项目.一个原型被定义为一个模式或者模型,表示全部东西都以一种相同的方式被建立.在Maven中,一个原型是一个根据用户需求而定制的结合了一些用户输入来产生的Maven工做项目的模版.如今咱们将向你展现一个原型机制是如何工做的,但若是你想知道更多关于原型的介绍,请参考: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

一旦你执行了这个命令,你将会发现一些东西发生了改变.首先,你会发现Maven为新项目建立了一个名为my-app的目录,而且这个目录包含了一个叫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>
  <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包含了这个项目的项目对象模型(project object model-POM).在Maven中,POM是基础工做单元.须要牢记这一点,由于Maven天生是项目式的,一切围绕项目的概念.简而言之,POM包含了你项目的全部重要信息片而且本质上是为查找任何项目相关内容的优惠条件...理解POM的重要性,而且咱们鼓励新用户查阅完整的POM介绍:http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

这是一个很是简单的POM可是仍然展现了全部POM都包含的关键元素,因此让咱们浏览每一个元素来使你熟悉POM的要点:

<project> 在全部pom.xml文件中,它都是顶级元素

<modelVersion> 这个元素代表了这个POM正在使用的对象模型的版本.模型自己的版本不多发生变化,可是它是强制性的以确保稳定的使用若是Maven开发人员认为有必要改变模型.

<groupId> 这个元素代表了建立项目的组织或团体的惟一标识符.它是项目的一个关键标识符而且一般基于组织的彻底限定域名.例如:org.apache.maven.plugins 是全部Maven插件的指定groupId.

<artifactId> 这个元素代表由项目生成的主要工件的惟一基础名称.项目的主要工件一般是JAR文件.次要工件像代码束也使用artifactId做为它们最后名字的一部分.一个Maven产生的特定工件可能会是这样的格式:<artifactId>-<version>.<extension> (如 myapp-1.0.jar).

<packaging> 这个元素代表工件用来打包的类型(如:JAR,WAR,EAR等).这不只仅意味着工件产生的是JAR,WAR,EAR...还代表了构建过程当中的一个特定的生命周期(生命周期是一个咱们将要讨论的主题,如今,只须要记住一个项目的包装能够做为定制构建生命周期的一部分).该元素的默认值是JAR,因此对于大多数项目来讲你不必定要指明这个元素.

<version> 这个元素代表项目生成的工件版本号.Maven帮你进行长期的版本管理,并且你常常会看见SNAPSHOT版本标志,这代表项目正处于一个开发状态.咱们将在后续讨论快照的用处和它们是如何工做的.

<name> 这个元素代表项目的展示名称.这一般被Maven用来生成文档.

<url> 这个元素代表项目站点的访问路径. 这一般被Maven用来生成文档.

<description> 这个元素提供了项目的基础描述. 这一般被Maven用来生成文档.

若是想要查看完整的可用元素请查阅:https://maven.apache.org/ref/3.3.9/maven-model/maven.html

如今咱们回到项目,在你的第一个项目的原型生成后,你也会发现以下目录结构被建立:

my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java

正如你所看见的,从原型建立的项目有一个POM,一个应用代码的代码树和测试代码的代码树.这是Maven项目的标准布局(应用代码被放置在${basedir}/src/main/java而测试代码放置在${basedir}/src/test/java,其中${basedir}表明包含pom.xml的目录).

若是你在手动建立Maven项目,这个目录结构是咱们强烈建议的.这是Maven规范.想了解更多访问:http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html

如今,咱们有了一个POM,一些应用代码,一些测试代码,你也许会问...

我如何编译个人应用代码

切换目录到${basedir}并执行命令:

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安装,这可能会耗费至关一下子(在上述输出中,它耗费了四分钟).若是你再次执行这个命令,Maven就不会去下载并且能够快速执行命令.

正如你在上述输出中所看到的,编译好的class文件放在${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] ----------------------------------------------------------------------------

请注意:

1.Maven如今下载了更多的依赖.这些都是测试所须要的插件和依赖.(它已经有了编译所需的依赖因此不会再次下载)

2.在编译和运行测试以前Maven编译了main代码(全部的代码都是最新的由于咱们自从上次编译后没有作任何改变)

若是你只是想要简单额编译测试代码(不运行测试),能够执行以下命令:

mvn test-compile

如今你可以编译你的应用代码,测试代码,并运行测试,你将要进行下一个逻辑步骤因此你会问...

我如何建立一个JAR并安装到本地仓库

建立JAR是至关直接的经过执行下列命令:

mvn package

若是你看下项目的POM文件你会发现packaging元素被设置为jar.这就是Maven如何知道要经过上述命令来产生JAR文件的缘由.如今你能够查看${basedir}/target 目录而后你会看见生成的JAR文件.

如今你想要安装你已经生成的工件(JAR包)到本地仓库(默认地址是:${basedir}/.m2/repository).想要了解更多关于Respository请访问: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 <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] ----------------------------------------------------------------------------

注意surefire插件(执行测试的)以一个特定的命名惯例查找包含测试的文件.

默认状况下包含:

**/*Test.java
**/Test*.java
**/*TestCase.java

不包含:

**/Abstract*Test.java
**/Abstract*TestCase.java

你已经经历了设置,构建,测试,打包,安装一个指定Maven项目的过程.你可能已经注意到这已是绝大多数Maven项目会作的事情.而你所作的这一切都是基于一个18行的文件(POM).若是你使用提供了相同功能的典型的Ant构建文件来达到咱们目前为止所作的,你会发现仅仅刚开始它就将达到POM的两倍大小.Maven还有更多的功能提供给你而不须要添加任何额外的内容到咱们如今的POM中.而想在Ant中提供相同的功能你不得不添加额外的内容,而这更容易致使出错.

因此咱们还可以免费获得些什么?即便是像上述这么简单的POM这里也有大量开箱即用的插件可使用.咱们会提到一个专用的Maven推崇的特性之一:不须要任何工做,POM已经有足够的信息来为你的项目生成一个Web站点.你可能想要定制你的Maven站点,可是若是你时间紧迫,那么你仅仅须要提供项目的基本信息而后执行下面的命令:

mvn site

这里还有大量独立的目标能够被执行,例如:

mvn clean

这个命令将会移除target目录在开始构建数据以前以便它是新鲜的

也许你想生成一个Intellij IDEA描述的项目:

mvn idea:idea

这能够运行在项目的前一个想法--它将更新设置而不是新的开始

若是你使用Eclipse IDE:

mvn eclipse:eclipse

注意:一些相似的目标从Maven1.0到如今一直存在,如jar:jar,可是它们的行为并不像你所指望的.目前,jar:jar不会从新编译源码,它仅仅简单建立一个JAR在target/classes目录,它假设其余一块儿已经完成...

什么是SNAPSHOT版本

注意:在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版本要老.

在发布期间,版本从x.y-SNAPSHOT变成x.y.发布过程增长开发版到x.(y+1)-SNAPSHOT.例如:1.0-SNAPSHOT版发布成1.0版,而且新的开发版的版本为1.1-SNAPSHOT.

我如何使用插件

不管什么时候你想要自定义Maven项目的构建过程,它都经过添加或者从新配置插件.

Maven1.0的用户请注意:在Maven1.0中,你将添加一些preGoal到maven.xml,一些entries到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>将应用给定的参数到每一个编译插件的目标.在上述状况下,编译插件已经被做为构建过程当中的一部分在使用而这仅仅是改变了配置.还能够添加新的目标到过程当中,配置指定的目标.想要了解构建过程,请访问:http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

想找出可配置的插件,你能够查阅http://maven.apache.org/plugins/

想知道如何配置一个插件的可用参数,请查阅:http://maven.apache.org/guides/mini/guide-configuring-plugins.html

我如何添加资源到个人JAR

另外一个常见用例是能够被知足的:不对咱们上述的POM作任何改变就能够将资源打包进JAR.针对于这项任务,Maven仍然依靠标准目录布局,这意味着只要采用Maven标准惯例你就能够仅经过将资源放在一个标准目录结构就能够简单的将它们打包进JAR.

在咱们下面的例子中你能够看见咱们添加了一个用来存听任何咱们想要打包进JAR的资源的目录${basedir}/src/main/resources.Maven采用的规则至关简单:任何被放置在 ${basedir}/src/main/resources目录下的目录或文件将会被打包进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

因此你能够看见在咱们的例子中咱们有个包含了application.properties文件的META-INF目录被放置在了指定目录 ${basedir}/src/main/resources下.若是你解压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目录下.你也会在那里发现一些其余的文件如:MANIFEST.MF,pom.xml,pom.properties等,这些是Maven中JAR包的标准生成.Maven会默认生成一个若是你没有本身建立一个manifest.(你也能够修改默认manifest中的项,稍后你会接触到).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

为你的单元测试添加资源到类路径的作法和你添加资源进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中作到这点,咱们能够经过使用语法${<property name>}将目标属性的引用添加到资源文件中.这个属性能够是在pom.xml中定义的一个值,能够是用户setting.xml中定义的一个值,还能够是一个外部属性文件中的一个属性甚至是系统属性.

想在拷贝时过滤资源,只须要在你的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/resoures目录.全部咱们以前提供的信息都和默认值相同,可是由于filtering的默认值是false,因此为了覆盖这个值咱们要添加它到pom.xml并设置为true.

引用在pom.xml中定义的属性,属性名使用定义了相应值的XML元素名,由于根节点是project元素,因此${project.name}引用了项目的名称,${project.version}引用了项目的版本,${project.build.finalName}引用了构建项目打包后产生的文件的最终名称,等等.注意有些POM元素有默认值,因此不必在pom.xml中显式声明它们由于它们的值是可用的.相似的,用户setting.xml中的值能够经过以"settings"打头的属性名来引用(如:${settings.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
java.version=${java.version}
command.line.prop=${command.line.prop}

当咱们再次执行mvn process-resources(注意在命令中command.line.prop属性的定义),application.properties文件将会包含来自系统属性的值:

mvn process-resources "-Dcommand.line.prop=hello again"

我如何使用外部依赖

你可能已经发现咱们在上面的例子中已经使用了dependencies元素.事实上,你已是一直在使用外部依赖了,不过咱们这里会对它的具体工做原理稍微讨论些细节.想了解更多,请自行查阅:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

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>

对于每个外部依赖,你至少须要定义四项:groupId,artifactId,version,scope.前三项和pom.xml中用来构建项目的三个元素的含义相同.scope代表你的项目要怎么使用这些依赖,它的值能够是compile,test和runtime.要想了解全部你能够为依赖指定的详细信息,请查阅:http://maven.apache.org/ref/current/maven-model/maven.html

想了解依赖原理的全部信息,请查阅:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

经过这个依赖的信息,Maven将在构建项目的时候引用依赖.Maven引用的依赖从哪里来?Maven在你的本地仓库查询全部依赖.在前一章节,咱们从咱们的项目安装了工件 (my-app-1.0-SNAPSHOT.jar) 到本地仓库.一旦它安装到了那里,另外一个项目就能够经过在pom.xml中添加依赖信息来简单的引用这个jar:

<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会下载不少东西.(这些都是用来构建项目的插件所需的依赖).默认状况下,Maven使用的远程仓库是在http://repo.maven.apache.org/maven2/.你也能够设置本身的远程仓库(也许是大家公司的中央库)经过替换或者添加默认远程仓库.更多关于仓库的信息请查阅:http://maven.apache.org/guides/introduction/introduction-to-repositories.html

让咱们添加另外一个依赖到咱们的项目中.让咱们假设咱们已经添加了一些日志代码而且须要添加log4j做为依赖.首先,咱们须要知道log4j的 groupId,artifactId,version .咱们能够浏览ibiblio来查找它,或者使用Google搜索:"site:www.ibiblio.org maven2 log4j".搜索结果显示一个目录/maven2/log4j/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文件旁边,咱们能够看见一个目录对应到各个版本的log4j库.在每一个目录中,咱们能够找到实际的jar文件和pom文件和另外一个maven-matedata.xml文件.这里还会有对应的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到远程仓库

为了部署jars到一个外部仓库,你必须在pom.xml中配置仓库的URL并在settings.xml认证链接仓库的信息.

这里有个使用SCP,用户名/密码认证的例子:

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>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.xml:

<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服务器,而且它sshd_config文件中的参数"PasswordAuthentication"设置为"no",那么你每次链接都须要输入用户名密码来进行验证.(尽管你可使用另外一个ssh客户机来输入用户名密码进行登陆).因此可能想要切换成公钥验证.

若是在settings.xml中使用密码咱们应该保持谨慎.更多信息查阅: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

访问如下连接来学习如何为你的项目生成文档: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的目录包含以下项目描述:

<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>

注意<packaging>元素,它告诉Maven把项目构建成WAR.切换到webapp项目目录执行:

mvn clean 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:

<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文件中添加<parent>元素:

<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 clean install

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的<packaging>元素的值是"pom"而且定义了<modules>来罗列全部子模块.这告诉Maven在全部子项目上执行全部操做而不是在当前项目上.(使用非递归选项--non--recursive来覆盖命令的行为).

而后,咱们告诉WAR它须要my-app的JAR.这作了一些事情:它让WAR中的全部代码在类路径中均可用,它确保JAR包在WAR包以前被构建,它代表了JAR做为插件添加到了WAR的类库目录.

你也许已经发现junit-4.11.jar是一个依赖,可是没有出如今WAR包中.这是由于它的<scope>的值是"test",代表仅仅在测试时须要使用.因此他不会在编译的时候添加进来.

最后一步是包含父级定义.这和你可能熟悉的Maven1.0中的extend元素不一样:这确保经过在仓库中查询POM老是能够被放置即便项目是分布式的.

相关文章
相关标签/搜索