Maven项目依赖,构建配置,以及构建,全部这些都是要建模和表述的对象。这些对象经过一个名为项目对象模型(POM)的XML文件描述。java
如图2sql
图2shell
POM包含了四类描述和配置:apache
§项目整体信息api
包含一个项目的名称,项目的URL,发起组织,以及项目的开发者,贡献者列表和许可证。maven
§构建设置ide
可自定义Maven构建的默认行为,更改源码和测试代码的位置,能够添加新的插件,能够将插件目标绑定到生命周期,能够自定义站点生成参数。布局
§构建环境测试
构建环境包含了一下能在不一样环境中使用激活的profile。ui
§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>
Maven项目中的POM永远都是基础目录下的一个名为pom.xml的文件。
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。
一个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元素设置本身的属性,或者还可使用外部载入的文件中属性。
Maven能够管理内部和外部依赖。
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坐标的。
<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:用来排除传递性依赖。
注意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,而后在各个项目中导入这些依赖管理配置。