1.POM项目对象模型

 Maven项目依赖,构建配置,以及构建,所有这些都是要建模和表述的对象。这些对象通过一个名为项目对象模型(POM)的XML文件描述。

1.

1.1.POM包括的内容

如图2

173316646.png

图2

POM包含了四类描述和配置:

§项目总体信息

包含一个项目的名称,项目的URL,发起组织,以及项目的开发者,贡献者列表和许可证。

§构建设置

可自定义Maven构建的默认行为,更改源码和测试代码的位置,可以添加新的插件,可以将插件目标绑定到生命周期,可以自定义站点生成参数。

§构建环境

构建环境包含了一下能在不同环境中使用激活的profile。

§POM关系

定义自身的坐标。依赖于其他项目。包含子模块。


1.2.超级POM

超级POM,所有的项目都依赖于超级POM,超级POM是最基础的。超级POM定义了一组被所有项目共享的默认设置,位置是\apache-maven-3.0.5\lib 下的 maven-model-builder-3.0.5.jar 中的 org/apache/maven/model/pom-4.0.0.xml

注意超级POM关闭了从中央Maven仓库下载snapshot构建功能。

Maven开始于超级POM,然后使用一个或多个父POM覆盖默认配置,最后使用当前项目的POM来覆盖之前生成的配置结果。查看当前项目依赖的命令:mvn help:effective-pom。

最简单的POM

<project>

<modelVersion>4.0.0</modelVersion>

<groupId>org.sonatype.mavenbook.ch08</groupId>

<artifactId>simplest-project</artifactId>

<version>1</version>

</project>

1.3.POM语法

Maven项目中的POM永远都是基础目录下的一个名为pom.xml的文件。

1.3.1.项目版本

Maven项目发布版本号使用version编码。Maven的版本包括:主版本,次版本,增量版本,和限定版本。格式如下<major version>.<minor version>.<incremental version>-<qualifier>。限定版本用来标识里程碑构建:alpha和beta发布。限定版本通过连字符与主版本,次版本或增量版本隔离。例如:版本”1.3-beta-01“有一个主版本1,次版本3,和一个限定版本“beta-01”。

注意:Maven被设计成将构建版本和限定版本分离,但目前这种解析还是失败的。如:"alpha-2"和"alpha-10"  是用字符串进行比较的。这样"alpha-10"比"alpha-2"更旧。解决方法:定义为"alpha-02"和"alpha-10",就可避免此类问题的出现。

§SNAPSHOT版本

Maven版本可以包含一个字符串字面量来表示项目正处于活动开发状态。如果一个版本包含字符串"SNAPSHOT",Maven就会在安装或者发布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC。当你发布一个snapshot,只是发布了一个特定时间的快照版本。在构建的时候Maven会定期的从仓库中下载最新的snapshot。

§LATEST和RELEASE版本

LATEST是指构建最新的发布版或快照版。RELEASE是指仓库中最后的一个非快照版本。当依赖于一个插件或一个依赖时,可以使用特殊的版本值LATEST或者RELEASE。

1.3.2.属性引用

一个POM可以通过${}来包含对属性的引用,在Mavne读取POM的时候,他会在载入POM的时候替换这些属性引用。

§ env变量:操作系统或者shell的环境变量;

§project:POM的project属性,使用点标记的路径来引用POM元素的值;

§settings:引用Maven settings信息,使用点标记来引用settings.xml文件中元素的值;

§Java系统属性:所以可以通过java.lang.System中的getProperties()方法访问的属性可以成为POM属性,如${user.name},${user.home},${java.home}和${os.home};

§还可以通过Pom.xml或者setting.xml中的properties元素设置自己的属性,或者还可以使用外部载入的文件中属性。

1.4.项目依赖

Maven可以管理内部和外部依赖。

1.4.1.坐标

Maven坐标为各种构建引入了秩序,任何一个构建都必须有明确定义自己的坐标,而一组Maven坐标是通过一些元素定义的。

如下:

<project>

<groupId>org.sonatypr.nexus</groupId>

<artifactId>nexus-index</artifactId>

<version>2.0.0</version>

<packaging>jar</packaging>

</project>

 groupId:定义当前Maven项目隶属的实际项目。Maven项目和实际项目不一定是一对一的关系。一个实际项目往往会被划分成很多模块,所以groupId一般都定义与实际项目对应。表示方法与Java包名的表示方法相同。

       artifactId:该元素定义实际项目中的一个Maven项目(模块)。推荐做法是使用实际项目名称为artifactId的前缀。这样的好处在于方便从一个lib文件夹中找到某个项目的一组构建。

       version:该元素定义Maven项目当前所处的版本。

       packaging:该元素定义Maven项目的打包方式。首先,打包方式通常与所生成构件的文件扩展名对应。其次,打包方式会影响到构建的生命周期。例如jar打包和war打包会使用不同的命令。

       classifiler:该元素用来帮助定义构建输出的一些附属构件。例如Jave文档和源码。


只要提过正确的坐标元素,Maven就能找到对应的构件。项目构件的文件名是与坐标对应的,一般规则为artifactId-version[-calssifier].packaging。

   Maven仓库布局也是基于Maven坐标的。

1.4.2.依赖配置包含的元素

<project>

           ...

<dependencies>

                <dependency>

                <groupId>...</groupId>

                <artifactId>...</artifactId>

                <version>...</version>

                <type>...</type>

                <scope>...</scope>

                <optional>...</optional>

                <exclusions>

                     <exclusion>

                           ...

                     </exclusion>

                     <exclusion>

                           ...

                     </exclusion>

                </exclusions>

          </dependency>

     </dependencies>

</project>

根元素project下的dependencies可以包含一个或者多个dependency元素,以生命一个或者多个项目依赖。每个依赖可以包含的元素有:

groupId,artifactId,version:依赖的基本坐标,对于任何一个项目依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需求的依赖。

type:依赖类型,对应于项目坐标定义的packaging。大部分情况下,该元素不必生命,其默认值为jar。

scope:依赖范围。

optional:标记依赖是否可选。

exclusions:用来排除传递性依赖。

1.4.3.依赖范围

注意Maven在编译,测试,运行时会个使用一套classpath。

依赖范围是用来控制依赖与这三种classpath(编译classpath,测试classpath,运行classpath)的关系。Maven有以下几种依赖范围:

§compile:编译依赖范围。compile是默认的范围:如果没提供一个范围,那该依赖的范围就是编译范围。使用此以来范围的Maven依赖,对于编译,测试,运行三种classpath都有效。

§test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试的classpath有效,在编译主代码或者运行项目的使用时将无法使用此类依赖,典型的例子是JUnit。

§provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试的classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要改依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重新引入。

§runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行classpath有效,但在编译主代码是无效。典型的例之就是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口。

§system:系统依赖范围。该依赖与三种classpath的关系,和provided依赖范围完全一致。但是,使用system范围依赖时必须通过systemPath元素显示地制定依赖文件的路径。必须显示的提供一个对于本地系统中JRA文件路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。如:

<dependency>

<groupId>javax.sql</groupId>

 <artifactId>jdbc-stdext</artifactId>

 <version>2.0</version>

 <scope>system</scope>

 <systempath>${java.home}/lib/rt.jar</systempath.

</dependency>

§import(Maven2.0.9及以上):导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。该依赖只在dependencyManagement元素下才有效果,使用该范围的依赖通常指向一个POM,作为是经目标POM中的dependencyManagement配置导入并合并到当前POM的dependencyManagement元素中。

<dependencyManagement>

<dependencies>

<dependency>

<groupId>com.sun.pro</groupId>

<artifactId>jpro-action</artifactId>

<version>1.0-SNAPSHOT</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

注:上述代码中依赖的type值为pom,import范围依赖由于其特殊性,一般都是指向打包类型为pom的模块。如果多个项目,它们使用依赖版本都是一致的,则就可以定义一个使用dependencyManagement专门管理依赖的POM,然后在各个项目中导入这些依赖管理配置。