关于maven中版本控制问题

以前咱们说过Maven的版本分为快照和稳定版本,快照版本使用在开发的过程当中,方便于团队内部交流学习。而所说的稳定版本,理想状态下是项目到了某个比较稳定的状态,这个稳定包含了源代码和构建都要稳定。apache

maven中的仓库分为两种,snapshot快照仓库和release发布仓库。snapshot快照仓库用于保存开发过程当中的不稳定版本,release正式仓库则是用来保存稳定的发行版本。定义一个组件/模块为快照版本,只须要在pom文件中在该模块的版本号后加上-SNAPSHOT便可(注意这里必须是大写)缓存

 

maven2会根据模块的版本号(pom文件中的version)中是否带有-SNAPSHOT来判断是快照版本仍是正式版本。安全

若是是快照版本,那么在mvn deploy时会自动发布到快照版本库中,会覆盖老的快照版本,而在使用快照版本的模块,在不更改版本号的状况下,服务器

直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。若是是正式发布版本,那么在mvn deploy时会自动发布到正式版本库中,架构

而使用正式版本的模块,在不更改版本号的状况下,编译打包时若是本地已经存在该版本的模块则不会主动去镜像服务器上下载并发

使用SNAPSHOT具备透明性,变动会直接生效,但这样会被依赖者带来不稳定性和不肯定性,因此不该该被滥用maven

 

补充:工具

对于服务,biz是没有版本这一说的,运行的永远都是最新的版本,可是对于API是有版本的。学习

API提供接口,biz提供服务,通常来讲,版本往上升的话,API只增不减,而biz也随之增长实现,若是新版本删除了某个接口及实现,而调用者使用old version的依赖,尝试调用这个接口,就会调不到产生错误。 测试

 

Maven中创建的依赖管理方式基本已成为Java语言依赖管理的事实标准,Maven的替代者Gradle也基本沿用了Maven的依赖管理机制。在Maven依赖管理中,惟一标识一个依赖项是由该依赖项的三个属性构成的,分别是groupId、artifactId以及version。这三个属性能够惟一肯定一个组件(Jar包或者War包)。

其实在Nexus仓库中,一个仓库通常分为public(Release)仓和SNAPSHOT仓,前者存放正式版本,后者存放快照版本。若是在项目配置文件中(不管是build.gradle仍是pom.xml)指定的版本号带有’-SNAPSHOT’后缀,好比版本号为’Junit-4.10-SNAPSHOT’,那么打出的包就是一个快照版本。

快照版本和正式版本的主要区别在于,本地获取这些依赖的机制有所不一样。假设你依赖一个库的正式版本,构建的时候构建工具会先在本次仓库中查找是否已经有了这个依赖库,若是没有的话才会去远程仓库中去拉取。因此假设你发布了Junit-4.10.jar到了远程仓库,有一个项目依赖了这个库,它第一次构建的时候会把该库从远程仓库中下载到本地仓库缓存,之后再次构建都不会去访问远程仓库了。因此若是你修改了代码,向远程仓库中发布了新的软件包,但仍然叫Junit-4.10.jar,那么依赖这个库的项目就没法获得最新更新。你只有在从新发布的时候升级版本,好比叫作Junit-4.11.jar,而后通知依赖该库的项目组也修改依赖版本为Junit-4.11,这样才能使用到你最新添加的功能。

这种方式在团队内部开发的时候会变的特别蛋痛。假设有两个小组负责维护两个组件,example-service和example-ui,其中example-ui项目依赖于example-service。而这两个项目天天都会构建屡次,若是每次构建你都要升级example-service的版本,那么你会疯掉。这个时候SNAPSHOT版本就派上用场了。天天平常构建时你能够构建example-service的快照版本,好比example-service-1.0-SNAPSHOT.jar,而example-ui依赖该快照版本。每次example-ui构建时,会优先去远程仓库中查看是否有最新的example-service-1.0-SNAPSHOT.jar,若是有则下载下来使用。即便本地仓库中已经有了example-service-1.0-SNAPSHOT.jar,它也会尝试去远程仓库中查看同名的jar是不是最新的。有的人可能会问,这样不就不能充分利用本地仓库的缓存机制了吗?别着急,Maven比咱们想象中的要聪明。在配置Maven的Repository的时候中有个配置项,能够配置对于SNAPSHOT版本向远程仓库中查找的频率。频率共有四种,分别是always、daily、interval、never。当本地仓库中存在须要的依赖项目时,always是每次都去远程仓库查看是否有更新,daily是只在第一次的时候查看是否有更新,当天的其它时候则不会查看;interval容许设置一个分钟为单位的间隔时间,在这个间隔时间内只会去远程仓库中查找一次,never是不会去远程仓库中查找(这种就和正式版本的行为同样了)。

Maven版本的配置方式为:

<repository>
    <id>myRepository</id>
    <url>...</url>
    <snapshots>
        <enabled>true</enabled>
        <updatePolicy>XXX</updatePolicy>
    </snapshots>
</repository>

其中updatePolicy就是那4种类型之一。若是配置间隔时间更新,能够写做interval:XX(XX是间隔分钟数)。daily配置是默认值。

而在Gradle,能够设置本地缓存的更新策略。

onfigurations.all {

// check for updates every build
resolutionStrategy.cacheChangingModulesFor  0,'seconds'

}

固然也能够按照分钟或者小时来设置.

configurations.all {

resolutionStrategy.cacheChangingModulesFor  10, ‘minutes'

}
configurations.all {

resolutionStrategy.cacheChangingModulesFor  4, ‘hours'

}

因此通常在开发模式下,咱们能够频繁的发布SNAPSHOT版本,以便让其它项目能实时的使用到最新的功能作联调;当版本趋于稳定时,再发布一个正式版本,供正式使用。固然在作正式发布时,也要确保当前项目的依赖项中不包含对任何SNAPSHOT版本的依赖,保证正式版本的稳定性。

 

1、如何衡量项目的稳定状态呢?

1. 全部的自动化测试应当所有经过

2. 项目没有配置任何快照版本的依赖

3. 项目没有配置任何快照版本的插件

4. 项目所包含的代码都已经所有提交到了版本控制系统中

5.咱们应当再一次执行Maven构建,以确保项目的状态是OK的

6. 咱们将这一次变动提交到版本控制的主干中,并打上标签

只有知足了上述6个条件, 咱们就能够将这一个快照版本更新至发布版本

 

2、在开发的过程当中,版本号要如何进行变动呢?Maven是否有潜在的约定? 

咱们在开发的过程当中,下载jar包的时候常常会发现某个jar相似这样:1.2.3-beat-4.jar

多么复杂的一个名称。。。下面来解释一下,这里每一个数字的含义:

“ 1 ” :  表示该版本的第一个重大版本

“ 2 ” :  表示这是基于重大版本的第二个次要版本

“ 3 ” :  表示该次要版本的第三个增量

" beat-4" : 表示该增量的一个里程碑

用一个图来描述:

< 主版本 >  ------   < 次版本 > ------ < 增量版本 > ------ < 里程碑版本 >

主版本:表示了项目的重大架构变动  struts1 --  struts2

次版本:表示较大范围的功能增长和变化  Nexus1.5 ----   Nexus1.4

增量版本:通常表示重大Bug修复  

里程碑版本:指某一个版本的里程碑   *.*-alpha-1  *.*-beat-1

看起来有点麻烦啊, 可是在通常来讲,咱们只会声明主版本和次版本,增量版本和里程碑版本就不必定了。

注:maven中约定的版本次序:

对于主版本、次版本、增量版原本说他们的比较是基于数字的,所以:1.5>1.4>1.3>1.2.11>1.2.8

对于里程碑版原本说,比较是基于字符串的,所以:1.5>1.4>1.3>1.2.3>1.2.11 

3、主干、分支、标签

上面的笔记中提到了主干和标签,到底如何理解主干、分支、标签呢?

主干: 项目开发代码的主体,是从项目开始到当前都处于活动的状态,从这里能够得到项目最新的源代码和几乎全部的变动历史

分支: 从主干的某个点分离出来的代码拷贝,一般能够在不影响主干的前提下,在这里进行重大的bug修复或者实验性质的开发,若是达到了预期的目的,一般将这里的变动合并到主干中去。

标签: 用来标识主干或者分支的某个点的状态,以表明项目的某个稳定状态,也就是一般说的发布状态

这三个元素,能够清晰的描述出项目的版本管理,并且也已经成了一个默认的行业标准。

 

4、自动化版本发布

用久了手动版本发布以后,咱们会想到可否进行自动化的发布版本,答案是确定的,这将引入一个新的插件:Maven Release Plugin

经过一些必要的配置,就能够完成版本发布

Maven Release Plugin 插件简介:

该插件主要有三个目标:release: prepare,  release: rollback,  release: perform (什么是插件目标),在介绍分支自动化的时候还会引入branch目标

①release:prepare   准备版本发布,依次执行下列操做

1. 检查项目是否有未提交的代码

2. 检查项目是否有快照版本依赖

3. 根据用户的输入将快照版本升级为发布版

4. 将POM中的SCM信息更新为标签地址

5. 基于修改后的POM执行maven构建

6. 提交POM变动

7. 基于用户输入为代码打标签

8. 将代码从发布版升级为新的快照版

9.提交POM变动

release: rollback

回退release: prepare所执行的操做。将POM回退至release:prepare以前的状态,并提交。

注:该步骤不会删除release:prepare生成的标签,须要用户手动删除

release: perform

执行版本发布

签出release:prepare生成的标签中的源代码,并在此基础上执行mvn deploy命令打包并部署构件至仓库

 

注:要为项目发布版本,首先须要为其添加正确的版本控制系统信息(这是由于Maven Release Plugin须要知道版本控制系统的主干、标签等地址后才能执行相关操做)

 

②分支的自动化建立

先看一下Maven Release Plugin 的branch目标能帮助咱们作哪些事情

1. 检查本地有无未提交的代码

2. 将分支更改POM的版本,如:1.1.0-SNAPSHOT改为1.1.1-SNAPSHOT

3. 将POM中的SCM信息更新为分支地址

4. 提交以上更改

5. 将主干代码复制到分支中

6. 修改本地代码使其回退到分支前的版本(用户能够指定新的版本)

7. 提交本地更改

注:此时也必须正确的配置SCM信息

 

5、代码安全

代码安全是咱们比较关心的一个问题, 好比说,当咱们从中央仓库下载第三方构件的时候,咱们可能要去验证这些文件的合法性,或者当咱们发布项目后,使用咱们项目的人也要验证

引入一个新的插件:Maven GPG Plugin 自动的完成签名

在使用Maven GPG Plugin以前,首先须要肯定GPG是可用的,而后再POM中配置插件便可

pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>1.0</version>
    <executions>
         <execution>
        <id>sign-artifacts</id>
        <phase>verify</phase>
        <goals>
              <goal>sign</goal>
        </goals>
         </execution>
    </executions>
</plugin>

而后使用通常的Maven命令签名并发布项目构件

$mvn clean deploy -Dgpg.passphrase=****

注:

1. 若是不提供 -Dgpg.passphrase参数,运行时就会要求输入密码

相关文章
相关标签/搜索