關於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參數,運行時就會要求輸入密碼

相關文章
相關標籤/搜索