目前在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版本的依賴能夠屢次發佈(deploy)到倉庫中,也就是說同一個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到生產環境中,這樣對於變動直接生效,很方便。可是做爲技術人員的咱們其實應該很嚴謹地看待變動傳達的透明性,變動就意味着風險,透明性更是把風險完全隱藏了起來,生產環境中存在這樣的現象更是心驚膽戰。例如: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版本和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就變成了固定小版本的穩定版本,不會在變化了,也至關於正式版的功能了。固然之後也能夠解鎖,詳細請看對應文檔