Maven版本管理-Maven Release Plugin插件

官方网址

一、什么是版本管理

首先,这里说的版本管理(version management)不是指版本控制(version control),但是本文假设你拥有基本的版本控制的知识,了解subversion的基本用法。版本管理中说得版本是指构件(artifact)的版本,而非源码的版本(如subversion中常见的rXXX,或者git中一次提交都有个sha1的commit号)。

  比如我有一个项目,其artifactId为myapp,随着项目的进展,我们会生成这样一些jar:myapp-1.0-SNAPSHOT.jar,myapp-1.0.jar,myapp-1.1-SNAPSHOT.jar,myapp-1.0.1.jar等等。你可能会说,这很简单啊,我在POM中改个version,mvn clean install不就完了?但这只是表面,本文我将讲述,snapshot和release版本的区别,如何自动化版本发布(如果你的项目有几十个module,你就会觉得手工改POM来升级版本是很痛苦的事情),结合自动化发布的过程,这里还会介绍maven-release-plugin。此外,一些scm概念也会被涉及到,比如tag和branch。

二、前提:版本控制

不管怎样,我们都需要建立一个项目并提交到SCM中,这里我以subversion为例。你得有一个配置好的subversion repository,这里我建立了一个空的svn仓库,其地址为:https://192.168.1.100:8443/svn/myapp/ 现在,该目录下只有三个空的典型的子目录:/trunk/, branches/, tags/。分别用来存放主干,分支,以及标签。

  接着将项目导入到svn仓库中,到项目根目录,运行如下命令:

    svn import -m 'project initialization' https://192.168.1.100:8443/svn/myapp/trunk 
  (注意,这么做你会将目录下所有文件导入到svn库中,但是这其中某些目录和文件是不应该被导入的,如/target目录,以及eclipse相关的项目文件)

  目前,我们将项目的版本设置为1.0-SNAPSHOT。

三、为什么用SNAPSHOT?

我先说说如果没有SNAPSHOT会是什么样子。假设你的项目有2个模块,A,B,其中A依赖B。这三个模块分别由甲,乙两个个人负责开发。在开发过程中,因为A是依赖于B的,因此乙每次做一个改动都会影响到甲,于是,乙提交了一些更改后,需要让甲看到。这个时候,怎么做呢?乙对甲说,“你签出我的代码,build一下就OK了”,甲有点不情愿,但还是照做了,签出代码,svn clean install,然后,发现build出错了,有个测试没有pass。甲郁闷了,对乙说,“你的代码根本不能用,我不想build,你build好了给我”,乙看了看确实自己的代码build不过,于是回去解决了,然后打了个jar包,扔给甲,甲对了对groupId,artifactId,放到了自己的.m2/repository/目录下,OK,能用了。

  于是乙每次更新都这样做,打包,复制,然后甲粘贴,使用……渐渐的,大家发现这是个很笨的办法,这是纯手工劳动阿,程序员最BS的就是重复劳动。一天,甲对乙说,“你知道nexus么?你把你的jar发布到nexus上就可以了,我要用就自动去下载,这多棒!”乙说“哦?有这好东西,我去看看”于是乙发现了nexus这块新大陆,并成功的发布了B到nexus上。(见,Nexus入门指南,(图文) )。

  但是,请注意,我们这里的一切都假设没有SNAPSHOT,因此如果乙不更改版本,甲下载一次如B-1.0.jar之后,maven认为它已经有了正确的B的版本,就不会再重新下载。甲发现了这个问题,对乙说“你的更新我看不到,你更新了么?”乙说“不可能!我看看”,于是检查一下甲下载的C-1.0.jar,发现那是几天前的。乙一拍脑袋,说“这简单,我更新一下我的版本就好了,我发布个B-1.1.jar上去,你更新下依赖版本”,甲照做了,似乎这么做是可行的。

  这里有一个问题,一次提交就更新一个版本,这明显不是正确的管理办法,此外,乙得不停的通知甲更新对B的依赖版本,累不累阿?1.0,或者说1.1,2.0,都代表了稳定,这样随随便便的改版本,能稳定么?

  所以Maven有SNAPSHOT版本的概念,它与release版本对应,后者是指1.0,1.1,2.0这样稳定的发布版本。

  现在乙可以将B的版本设置成1.0-SNAPSHOT,每次更改后,都mvn deploy到nexus中,每次deploy,maven都会将SNAPSHOT改成一个当前时间的timestamp,比如B-1.0-SNAPSHOT.jar到nexus中后,会成为这个样子:B-1.0-20081017-020325-13.jar。Maven在处理A中对于B的SNAPSHOT依赖时,会根据这样的timestamp下载最新的jar,默认Maven每天 更新一次,如果你想让Maven强制更新,可以使用-U参数,如:mvn clean install -U 。

  现在事情简化成了这个样子:乙做更改,然后mvn deploy,甲用最简单的maven命令就能得到最新的B。

四、从1.0-SNAPSHOT到1.0到1.1-SNAPSHOT

 SNAPSHOT是快照的意思,项目到一个阶段后,就需要发布一个正式的版本(release版本)。一次正式的发布需要这样一些工作:

  1.   在trunk中,更新pom版本从1.0-SNAPSHOT到1.0
  2.   对1.0打一个svn tag
  3.   针对tag进行mvn deploy,发布正式版本
  4.   更新trunk从1.0到1.1-SNAPSHOT

  你可以手工一步步的做这些事情,无非就是一些svn操作,一些pom编辑,还有一些mvn操作。但是你应该明白,手工做这些事情,一来繁琐,而来容易出错。因此这里我介绍使用maven插件来自动化这一系列动作。

1. SCM

  首先我们需要在POM中加入scm信息,这样Maven才能够替你完成操作,这里我的配置如下:

<scm>  
  <connection>scm:svn:http://192.168.1.100:8443/svn/myapp/trunk/</connection>  
  <developerConnection>scm:svn:https://192.168.1.100:8443/svn/myapp/trunk/</developerConnection>  
</scm>  

如果你的项目中pom分多个模块,就需要使用命令:release:prepare-with-pom进行打包发布。

    本地打包只需要运行一个命令:mvn release:prepare-with-pom,该命令会执行操作并且将新打包的代码提交到svn。(参考  4. 开始工作)

    在发布之前,首先要配置依赖如下:

    parent父级模块的依赖(parent项目的pom.xml): 

<!-- scm配置,具体路径为待打包代码分支的根路径(trunk、branckes/v1.1.x、/tags/v1.1.5等) -->
    <scm>
          <developerConnection>scm:svn:svn://SVN主路径地址/trunk/</developerConnection>
     </scm> 
   <!-- maven-release-plugin插件配置 -->
    <build>
          <plugins>
              <plugin>
                   <groupId>org.apache.maven.plugins</groupId>
                   <artifactId>maven-release-plugin</artifactId>
                   <version>2.5.3</version>
                   <configuration>
                     <autoVersionSubmodules>true</autoVersionSubmodules>
                     <tagNameFormat>v@{project.version}</tagNameFormat>
                     <generateReleasePoms>false</generateReleasePoms>
                     <arguments>-DskipTests</arguments>
                </configuration>
              </plugin>
          </plugins>
     </build>

 2、 开始工作

mvn release:clean  清除release生成的相关临时配置

mvn release:prepare  生成release生成的相关临时配置,生成tag到本地

mvn release:perform 将prepare生成的配置推送到中央仓库

五、Maven的版本规则

前面我们提到了SNAPSHOT和Release版本的区别,现在看一下,为什么要有1.0,1.1,1.1.1这样的版本,这里的规则是什么。

  Maven主要是这样定义版本规则的:

    <主版本>.<次版本>.<增量版本>[可选]

  比如说1.2.3,主版本是1,次版本是2,增量版本是3。

     可选的一般有 

  SNAPSHOT(快照,开发版)

  alpha(内部测试)

   beta(公开测试)

  Release|RC(发布版)

  GA(正常版本)

  主版本一般来说代表了项目的重大的架构变更,比如说Maven 1和Maven 2,在架构上已经两样了,将来的Maven 3和Maven 2也会有很大的变化。次版本一般代表了一些功能的增加或变化,但没有架构的变化,比如说Nexus 1.3较之于Nexus 1.2来说,增加了一系列新的或者改进的功能(仓库镜像支持,改进的仓库管理界面等等),但从大的架构上来说,1.3和1.2没什么区别。至于增量版本,一般是一些小的bug fix,不会有重大的功能变化。

  一般来说,在我们发布一次重要的版本之后,随之会开发新的版本,比如说,myapp-1.1发布之后,就着手开发myapp-1.2了。由于myapp-1.2有新的主要功能的添加和变化,在发布测试前,它会变得不稳定,而myapp-1.1是一个比较稳定的版本,现在的问题是,我们在myapp-1.1中发现了一些bug(当然在1.2中也存在),为了能够在段时间内修复bug并仍然发布稳定的版本,我们就会用到分支(branch),我们基于1.1开启一个分支1.1.1,在这个分支中修复bug,并快速发布。这既保证了版本的稳定,也能够使bug得到快速修复,也不同停止1.2的开发。只是,每次修复分支1.1.1中的bug后,需要merge代码到1.2(主干)中。

  上面讲的就是我们为什么要用增量版本。

六、小结

  本文讲述了如何使用Maven结合svn进行版本管理。解释了Maven中SNAPSHOT版本的来由,以及Maven管理版本的规则。并结合SCM的tag和branch概念展示了如何使用maven-release-plugin发布版本,以及创建分支。本文涉及的内容比较多,且略显复杂,不过掌握版本管理的技巧对于项目的正规化管理来说十分重要。Maven为我们提供了一些一套比较成熟的机制,值得掌握

posted @ 2020-04-01 09:28  HansonYao  阅读(772)  评论(0编辑  收藏  举报