Maven项目中的POM永远都是基础目录下的一个名为pom.xml
的文件。这个XML文档可以以XML声明开头,或者你也可以选择忽略它。所有的POM的值都通过XML元素的形式体现。
一个Maven项目发布版本号用version
编码,用来分组和排序发布。Maven中的版本包含了以下部分:主版本,次版本,增量版本,和限定版本号。一个版本中,这些部分对应如下的格式:
<major version>.<minor version>.<incremental version>-<qualifier>
例如:版本“1.3.5”由一个主版本1,一个次版本3,和一个增量版本5。而一个版本“5”只有主版本5,没有次版本和增量版本。限定版本用来标识里程碑构建:alpha和beta发布,限定版本通过连字符与主版本,次版本或增量版本隔离。例如,版本“1.3-beta-01”有一个主版本1,次版本3,和一个限定版本“beta-01”。
当你想要在你的POM中使用版本界限的时候,保持你的版本号与标准一致十分重要。在Section 9.4.3, “依赖版本界限”中介绍的版本界限,允许你声明一个带有版本界限的依赖,只有你遵循标准的时候该功能才被支持。因为Maven根据本节中介绍的版本号格式来对版本进行排序。
如果你的版本号与格式<主版本>.<次版本>.<增量版本>-<限定版本>相匹配,它就能被正确的比较;“1.2.3”将被评价成是一个比“1.0.2”更新的构件,这种比较基于主版本,次版本,和增量版本的数值。如果你的版本发布号没有符合本节介绍的标准,那么你的版本号只会根据字符串被比较;“1.0.1b”和“1.2.0b”会使用字符串比较。
我们还需要对版本号的限定版本进行排序。以版本号“1.2.3-alpha-2”和“1.2.3-alpha-10”为例,这里“alpha-2”对应了第二次alpha构建,而“alpha-10”对应了第十次alpha构建。虽然“alpha-10”应该被认为是比“alpha-2”更新的构建,但Maven排序的结果是“alpha-10”比“alpha-2”更旧,问题的原因就是我们刚才讨论的Maven处理版本号的方式。
Maven会将限定版本后面的数字认作一个构建版本。换句话说,这里限定版本是“alpha”,而构建版本是2。虽然Maven被设计成将构建版本和限定版本分离,但目前这种解析还是失效的。因此,“alpha-2”和“alpha-10”是使用字符串进行比较的,而根据字母和数字“alpha-10”在“alpha-2”前面。要避开这种限制,你需要对你的限定版本使用一些技巧。如果你使用“alpha-02”和“alpha-10”,这个问题就消除了,一旦Maven能正确的解析版本构建号之后,这种工作方式也还是能用。
Maven版本可以包含一个字符串字面量来表示项目正处于活动的开发状态。如果一个版本包含字符串“SNAPSHOT”,Maven就会在安装或发布这个组件的时候将该符号展开为一个日期和时间值,转换为UTC(协调世界时)。例如,如果你的项目有个版本为“1.0-SNAPSHOT”并且你将这个项目的构件部署到了一个Maven仓库,如果你在UTC2008年2月7号下午11:08部署了这个版本,Maven就会将这个版本展开成“1.0-20080207-230803-1”。换句话说,当你发布一个snapshot,你没有发布一个软件模块,你只是发布了一个特定时间的快照版本。
那么为什么要使用这种方式呢?SNAPSHOT版本在项目活动的开发过程中使用。如果你的项目依赖的一个组件正处于开发过程中,你可以依赖于一个SNAPSHOT版本,在你运行构建的时候Maven会定期的从仓库下载最新的snapshot。类似的,如果你系统的下一个发布版本是“1.4”你的项目需要拥有一个“1.4-SNAPSHOT”的版本,之后它被正式发布。
作为一个默认设置,Maven不会从远程仓库检查SNAPSHOT版本,要依赖于SNAPSHOT版本,用户必须在POM中使用repository
和pluginRepository
元素显式的开启下载snapshot的功能。
当发布一个项目的时候,你需要解析所有对SNAPSHOT版本的依赖至正式发布的版本。如果一个项目依赖于SNAPSHOT,那么这个依赖很不稳定,它随时可能变化。发布到非snapshot的Maven仓库(如http://repo1.maven.org/maven2)的构件不能依赖于任何SNAPSHOT版本,因为Maven的超级POM对于中央仓库关闭了snapshot。SNAPSHOT版本只用于开发过程。
当你依赖于一个插件或一个依赖,你可以使用特殊的版本值LATEST或者RELEASE。LATEST是指某个特定构件最新的发布版或者快照版(snapshot),最近被部署到某个特定仓库的构件。RELEASE是指仓库中最后的一个非快照版本。总得来说,设计软件去依赖于一个构件的不明确的版本,并不是一个好的实践。如果你处于软件开发过程中,你可能想要使用RELEASE或者LATEST,这么做十分方便,你也不用为每次一个第三方类库新版本的发布而去更新你配置的版本号。但当你发布软件的时候,你总是应该确定你的项目依赖于某个特定的版本,以减少构建的不确定性,免得被其它不受你控制的软件版本影响。如果无论如何你都要使用LATEST和RELEASE,那么要小心使用。
Maven 2.0.9之后,Maven在超级POM中锁住了一些通用及核心Maven插件的版本号,以将某个特定版本Maven的核心Maven插件组标准化。这个变化在Maven 2.0.9中被引入,为Maven构建带来了稳定性和重现性。在Maven 2.0.9之前,Maven会自动将核心插件更新至LATEST版本。这种行为导致了很多奇怪现象,因为新版本的插件可能会有一些bug,甚至是行为变更,这往往使得原来的构建失败。当Maven自动更新核心插件的时候,我们就不能保证构建的重现性,因为插件随时都可能从中央仓库更新至一个新的版本。从Maven 2.0.9开始,Maven从根本上锁住了一组核心插件的版本。非核心插件,或者说没有在超级POM中指定版本的插件仍然会使用LATEST版本去从仓库获取构件。由于这个原因,你在构件中使用任何一个自定义非核心插件的时候,都应该显式的指定版本号。