在Maven中如何恰当的管理版本

目前在JAVA的世界中,maven已经成为事实上的构建标准,不少开源库的管理构建也是基于maven的,maven自己的学习曲线比较陡峭,遵循“约定优于配置”的理念,maven存在不少约定。本次我先描述下,关于版本的定义的选择,SNAPSHOT or RELEASE?服务器

版本之争

在maven的约定中,依赖的版本分为两类——SNAPSHOT和RELEASE。SNAPSHOT依赖泛指以-SNAPSHOT为结尾的版本号,例如1.0.1-SNAPSHOT。除此以外,全部非-SNAPSHOT结尾的版本号则都被认定为RELEASE版本,即正式版,虽然会有beta、rc之类说法,可是这些只是软件工程角度的测试版,对于maven而言,这些都是RELEASE版本。既然Maven提供了这两类版本号,那么他们以前的优劣势是什么?分别在什么场景下使用?maven

解读SNAPSHOT

同一个SNAPSHOT版本的依赖能够屡次发布(deploy)到仓库中,也就是说同一个SNAPSHOT版本的依赖能够在仓库中存在多份,每一份都是代码在某一个特定时间的快照,这也是SNAPSHOT的含义。学习

snapshot

如上图,很好地表达了SNAPSHOT的细节,也阐述了一个SNAPSHOT很重要观点——SNAPSHOT不是一个特定的版本,而是一系列的版本的集合,其中HEAD老是指向最新的快照,对外界可见的通常也是最新版,这种给人的假象是新的覆盖了老的,从而使得使用SNAPSHOT依赖的客户端老是经过从新构建(有时候须要-U强制更新)就能够拿到最新的代码。例如:A-->B-1.3.8-SNAPSHOT(理解为A依赖了B的1.3.8-SNAPSHOT版本),那么B-1.3.8-SNAPSHOT更新以后从新deploy到仓库以后,A只须要从新构建就能够拿到最新的代码,并不须要改变依赖B的版本。因而可知,这样达到了变动传达的透明性,这对于开发过程当中的团队协做的帮助不言而喻。测试

SNAPSHOT之殇

SNAPSHOT版本的依赖由于存在变动传达的透明性的优点而被赏识,甚至被“溺爱”,有不少团队索性直接使用SNAPSHOT到生产环境中,这样对于变动直接生效,很方便。可是做为技术人员的咱们其实应该很严谨地看待变动传达的透明性,变动就意味着风险,透明性更是把风险完全隐藏了起来,生产环境中存在这样的现象更是心惊胆战。例如:A-->B.1.0.3-SNAPSHOT,B对一个A使用的功能实现进行了调整,直接发布到仓库,A从新构建或许就会失败,更糟糕的是构建成功,运行时异常。这个时候A甚至彻底没有代码变动就忽然失败了,会带来更多的困惑。spa

这也是maven常常遭人诟病的一个因素,对于同一份代码,构建结果却不具有肯定性,让不少人沮丧。固然这个不彻底是由于依赖的问题,也有maven插件的问题,maven以前的版本寻找插件策略的方式也存在不肯定性,maven在版本2的时候,会去寻找最新的插件版本(若是没配置的话)来执行构建,常常会找到SNAPSHOT版本的插件,因此依赖了一个不稳定的插件来执行构建,不肯定性就大大增长。不过maven在3版本就改变了这个策略,会寻找最新稳定版的插件来执行构建,使得构建具有了肯定性,稳定性也好多了。说明maven自己也在SNAPSHOT的问题上狠狠摔了一跤。插件

归根到底,这些问题的根源就是SNAPSHOT是变化的,是不稳定的,而应用(软件)依赖于变化而且不稳定的SNAPSHOT的依赖会致使自身也在变化和不稳定中,这是稳定性的一个大忌,依赖不稳定的服务或者依赖,上述的maven2的问题就是一个典型反例。开发

RELEASE简介

RELEASE版本和SNAPSHOT是相对的,非SANPSHOT版本即RELEASE版本,RELEASE版本是一个稳定的版本号,看清楚咯,是一个,不是一系列,能够认为RELEASE版本是不可变化的,一旦发布,即永远不会变化。文档

虽然RELEASE版本是稳定不变的,可是仓库仍是有策略让这个原则变得可配置,有的仓库会配置成redeploy覆盖,这样RELEASE版本就变成SNAPSHOT了,假装成RELEASE的SNAPSHOT,会让问题更费解和棘手,我通常称这类人为“挖坑专家”。部署

记住,RELEASE一旦发布,就不可改变。get

如何选择

那么何时使用SNAPSHOT?何时使用RELEASE?这个能够从他们各自的特性上来看,SNAPSHOT版本的库是一直在变化的,或者说随时都会变化的,这样虽然能够获取到最新的特性,可是也存在不稳定因素,依赖一个不稳定的模块或者库会让模块自身也变得不稳定,尤为是自身对被依赖模块的变化超出掌控的状况。即便能够掌控被依赖模块的变化,也会带来不稳定的因素,由于每次变动都有引入bug的可能性。若是这么说,那么咱们是否是要摒弃SANPSHOT了呢?答案确定是否认的。

想象下,什么状况下,模块会一直变化或者变化比较剧烈?开发新特性的时候,因此对于团队之间协同开发的时候,模块之间出现依赖,变化会很是剧烈,如模块A依赖模块B,模块A必然须要最方便地获取模块B的特性,在开发期间,方便性比稳定性更重要。能够反证下,假设模块B使用RELEASE版本1.0.0,模块A依赖1.0.0,如今模块A出现了bug,须要修复下,那么A就要提供一个版本号1.0.1,这样全部依赖A模块都须要更新版本号,由于开发期间这种事情是如此多,因此会带来巨变。反观SNAPSHOT方案,若是模块B的版本是1.0.0-SNAPSHOT,模块A彻底不须要修改版本号便可获取模块B的新特性。当开发进入预发布阶段,为了生产环境的稳定性,依赖应该是RELEASE版本,由于此时SNAPSHOT版本的模块自动获取新特性的特色偏偏会形成生产环境的不稳定性,生产环境上,稳定性重于一切。

Maven有SNAPSHOT版本的概念,其目的就是让你可以构建一个临时的版本,供团队他人使用,这样他们就没必要在代码的层次关心本身的依赖。因而私有Maven仓库就充当了一个中介的做用,而持续集成服务器就多了一个职责,每次它成功构建一个模块,都应该将该模块的SNAPSHOT版本发布到Maven仓库中。如今,你们就不用去构建别人的代码了,Maven能自动帮你从私有仓库解析下载依赖的最新SNAPSHOT(使用mvn命令的-U参数强制更新)。注意,除了持续集成服务器外,任何其余人都不该该发布SNAPSHOT版本到Maven仓库,由于只有持续集成服务器的环境是可信任的,你能在本地成功执行mvn clean install并不表明持续集成服务器上该命令能成功,因为每一个人的本地环境各有差别,所以集成的成功与否应当以持续集成服务器为准,而只有集成成功后,SNAPSHOT才能够被部署到私有仓库供他人使用。

魔幻之手

如今已经很明确了,在开发期间,活跃模块的版本号使用SNAPSHOT,在生产期间,依赖RELEASE版本模块。貌似,咱们找到了银弹,不过这个只是理想状态,即全部的模块的版本都在本身的掌控或者间接掌控下,只有这样你才能影响对应模块的版本号。每每是理想很丰满,现实却很骨感,若是你依赖的一个模块只有SNAPSHOT版本,而且该模块也很活跃,最无助的是模块的维护人不理会你的请求,那么是否就没辙了,只能把应用构建在不稳定模块上呢?介绍一款maven插件——Version,这是一个很是强大的版本管理插件,其中有个对依赖版本加锁的特性——lock-snapshots,而且提供了参数能够控制锁定的依赖,就能够实现对特定的SNAPSHOT模块锁定版本,执行的命令以下:mvn versions:lock-snapshots -DincludesList="groupId:artifactId:type:classifier:version",执行这个命令以后,对应的版本号会变化,好比1.0.0-SNAPSHOT会变成1.0.0.20090327.172306-4,即完成了锁定,此时这个SNAPSHOT就变成了固定小版本的稳定版本,不会在变化了,也至关于正式版的功能了。固然之后也能够解锁,详细请看对应文档

相关文章
相关标签/搜索