這又是一個系列,一個要把Maven講透的系列,但願可以對你們有幫助!
在前面的幾篇關於Maven的總結中,都說到只要指定了groupId
、artifactId
和version
座標信息,就能夠從中央倉庫中找到對應的jar包。等一下,倉庫?你們確定會問,倉庫是什麼?這個倉庫在哪裏?爲何Maven會自動去那個倉庫找我要的jar包呢?好的,我知道你們確定有一堆的疑問,一頭霧水,這篇文章就來解決你們的這些疑問,撥開疑霧,對這個「倉庫」一探究竟。跟着個人步伐,Let's go!apache
如今你們想一下之間開發的非Maven項目,是否是在每一個項目下面都有一個lib目錄。是的,你不用去翻看你之前作的項目了,沒有錯,沒有Maven以前,咱們項目依賴的包,咱們都會下載下來,統一放到對應項目的lib目錄下去。同一個包,好比Spring框架的包,項目A要使用,就拷貝一份到項目A的lib目錄下去;項目B也要使用,那就再拷貝一份到項目B的目錄下去。這樣下去,你會發現一樣的依賴包,須要拷貝N份,這樣不只形成了磁盤空間的浪費,並且也難於統一管理。瀏覽器
如今好了,有了Maven,基於Maven的座標機制,任何Maven項目使用任何一個構件的方式都是徹底相同的。在此基礎上,Maven能夠在某個位置統一存儲全部Maven項目共享的包,而這個統一存放依賴包的位置就是倉庫。說白了,Maven倉庫就是存放依賴包的地方。緩存
有了這個Maven倉庫後,上面的問題就有了一個完美的解決方案。基於Maven開發的項目再也不各自存儲其依賴文件,它們只須要聲明這些依賴的座標,在須要的時候,Maven會自動根據座標找到倉庫中的包,並正確使用它們。安全
在使用Maven的過程當中,咱們須要知道Maven去哪裏找那個所謂的「倉庫」,從而加載依賴。因此,咱們就須要知道Maven倉庫的分類。微信
在Maven中,倉庫分爲如下兩類:架構
Maven根據依賴座標去倉庫中找對應的包,是遵循這樣的一個軌跡:框架
上面簡單將Maven倉庫進行的分類,可是對於遠程倉庫,它又分爲好幾種:maven
本地倉庫
上面也說到了Maven根據依賴座標去倉庫中找對應的包是有遵循的軌跡的。Maven最開始都是從本地倉庫尋找依賴的包。默認狀況下,無論是在Windows仍是在Linux上,每一個用戶在本身的用戶目錄下都有一個路徑名爲.m2/repository
的倉庫目錄。這個就是默認的本地倉庫地址。工具
有的時候,用戶可能會自定義本地倉庫的目錄地址(我通常都會這麼幹)。此時,能夠經過編輯~/.m2/settings.xml
,設置localRepository
元素的值就OK了,好比個人是這樣子的:佈局
<localRepository>E:/repository</localRepository>
這樣,該用戶的本地倉庫地址就被設置成了E:/repository。
中央倉庫
因爲最開始的本地倉庫是空的,Maven必須知道至少一個可用的遠程倉庫,這樣才能在執行Maven命令的時候下載到須要的構件。中央倉庫就是這樣一個默認的遠程倉庫,Maven的安裝文件中自帶了中央倉庫的配置。使用解壓縮工具打開$M2_HOME/lib/maven-model-builder-3.5.0.jar
文件,在org\apache\maven\model
目錄下有一個pom-4.0.0.xml
文件,該文件裏面有這麼一段代碼,它配置了默認的中央倉庫:
<repositories> <repository> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
pom-4.0.0.xml文件是全部Maven項目都會繼承的超級POM,這段配置使用id central對中央倉庫進行惟一標識,同時設置snapshots元素,其子元素enabled的值爲false,表示不從該中央倉庫下載快照版本的包。
中央倉庫是一個大而全的包倉庫,它包含了這個世界上絕大多數流行的開源Java包,以及源碼等信息。通常來講,一個簡單Maven項目所須要的依賴包都能從中央倉庫下載到,這也就解釋了爲何Maven能作到「開箱即用」。
私服
玩遊戲的時候,常常會聽到私服。可是在學習Maven的時候,也聽到私服,這個就比較特殊了。在Maven中,私服是一種特殊的遠程倉庫,它是架設在局域網內的倉庫服務,私服代理廣域網上的遠程倉庫,供局域網內的Maven用戶使用。總體架構以下圖所示:
當Maven須要下載依賴包的時候,它從私服請求,若是私服上不存在該依賴包,則從外部的遠程倉庫下載,緩存到私服上以後,再爲Maven的下載請求提供服務。另外,一些沒法從外部倉庫下載到的依賴包也能從本地上傳到私服上供你們使用。
爲啥要用私服呢?確定是有少好處的。像在咱們公司,在全國31個省都有分公司,同時總部研發中心還會開發一堆的公共JAR包,給31個分公司使用,這樣經過私服就能夠很好的解決研發中心和分公司之間的公共包分發等問題。對於使用私服,它有如下這些優勢:
沒有一個平臺可以大而全到包含全部的東西,同理,中央倉庫也是這樣的,雖然它包含了咱們須要的大部分的依賴包,可是仍是有一些包在中央倉庫中是找不到的。這個時候,咱們就須要配置一些其它遠程倉庫來補充中央倉庫中沒有的依賴包,與中央倉庫配合完成工做,當中央倉庫也沒有對應的依賴包時,Maven則遍歷全部的遠程倉庫。
咱們須要在pom.xml中配置便可,好比這樣:
<project> ...... <!-- 配置遠程倉庫 --> <repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.com/maven2/</url> <releases> <enabled>true</enabled> <updatePolicy>daily</updatePolicy> </releases> <snapshots> <enabled>false</enabled> <checksumPolicy>warn</checksumPolicy> </snapshots> <layout>default</layout> </repository> </repositories> ...... </project>
repository
:在repositories
元素下,可使用repository
子元素聲明一個或者多個遠程倉庫。id
:倉庫聲明的惟一id,尤爲須要注意的是,Maven自帶的中央倉庫使用的id爲central,若是其餘倉庫聲明也使用該id,就會覆蓋中央倉庫的配置。name
:倉庫的名稱,讓咱們直觀方便的知道倉庫是哪一個,暫時沒發現其餘太大的含義。url
:指向了倉庫的地址,通常來講,該地址都基於http協議,Maven用戶均可以在瀏覽器中打開倉庫地址瀏覽構件。releases
和snapshots
:用來控制Maven對於發佈版構件和快照版構件的下載權限。須要注意的是enabled子元素,該例中releases的enabled值爲true,表示開啓JBoss倉庫的發佈版本下載支持,而snapshots的enabled值爲false,表示關閉JBoss倉庫的快照版本的下載支持。根據該配置,Maven只會從JBoss倉庫下載發佈版的構件,而不會下載快照版的構件。layout
:元素值default表示倉庫的佈局是Maven2及Maven3的默認佈局,而不是Maven1的佈局。基本不會用到Maven1的佈局。元素updatePolicy用來配置Maven從遠處倉庫檢查更新的頻率,默認值是daily,表示Maven天天檢查一次。其餘可用的值包括:never-從不檢查更新;always-每次構建都檢查更新;interval:X-每隔X分鐘檢查一次更新(X爲任意整數)。
元素checksumPolicy用來配置Maven檢查校驗和文件的策略。當構建被部署到Maven倉庫中時,會同時部署對應的檢驗和文件。在下載構件的時候,Maven會驗證校驗和文件,若是校驗和驗證失敗,當checksumPolicy的值爲默認的warn時,Maven會在執行構建時輸出警告信息,其餘可用的值包括:fail-Maven遇到校驗和錯誤就讓構建失敗;ignore-使Maven徹底忽略校驗和錯誤。
大部分公共的遠程倉庫無須認證就能夠直接訪問,但咱們在平時的開發中每每會架設本身的Maven遠程倉庫,出於安全方面的考慮,咱們須要提供認證信息才能訪問這樣的遠程倉庫。配置認證信息和配置遠程倉庫不一樣,遠程倉庫能夠直接在pom.xml中配置,可是認證信息必須配置在settings.xml文件中。這是由於pom每每是被提交到代碼倉庫中供全部成員訪問的,而settings.xml通常只存在於本機。所以,在settings.xml中配置認證信息更爲安全。好比這樣配置:
<servers> <server> <id>deploymentRepo</id> <username>repouser</username> <password>repopwd</password> </server> </servers>
這裏的關鍵是id元素,settings.xml中server元素的id必須與pom.xml中須要認證的repository元素的id徹底一致。正是這個id將認證信息與倉庫配置聯繫在了一塊兒。
不少時候,咱們編譯完成後,會將咱們的負責的模塊包部署至私服,以供其它團隊成員使用。那如何將咱們的包部署到遠程倉庫呢?
咱們配置項目的pom.xml文件便可,配置以下所示:
<project> ...... <distributionManagement> <repository> <id>releases</id> <name>public</name> <url>http://59.50.95.66:8081/nexus/content/repositories/releases</url> </repository> <snapshotRepository> <id>snapshots</id> <name>Snapshots</name> <url>http://59.50.95.66:8081/nexus/content/repositories/snapshots</url> </snapshotRepository> </distributionManagement> ...... </project>
distributionManagement包含repository和snapshotRepository子元素,前者表示發佈版本(穩定版本)構件的倉庫,後者表示快照版本(開發測試版本)的倉庫。
配置正確後,運行mvn clean deploy
命令,Maven就會將項目構建輸出的構件部署到配置對應的遠程倉庫,若是項目當前的版本是快照版本,則部署到快照版本的倉庫地址,不然就部署到發佈版本的倉庫地址。
若是去你的本地倉庫,你可能會看到以這種相似於1.0.0、1.3-alpha-一、2.0、2.1-SNAPSHOT或者2.1-20190412.221213-52這樣的版本號命名的JAR包。其中,1.0.0、1.3-alpha-1和2.0是穩定的發佈版本,而2.1-SNAPSHOT和2.1-20190412.221213-52是不穩定的快照版本。
Maven爲何要區分發布版本和快照版本呢?爲何還要有2.1-SNAPSHOT和2.1-20190412.221213-52這樣的命名區分呢?
如今咱們來思考一種現實的開發場景。如今軟件開發都是多人分模塊開發,好比小明開發A模塊,你開發B模塊,而你的B模塊是須要依賴A模塊的,在開發過程當中,小明須要常常將本身最新的代碼提交編譯,生成A模塊包,交給你,供你開發和集成調試。這種開發場景,如何完美的實現多人協同開發、模塊開發呢?
你可能想你本身每次單獨從代碼更把A模塊代碼Pull下來,本身編譯,生成本身須要的依賴包。這麼作沒有問題,可是帶來的問題是你須要去拉代碼,還要去編譯別人的模塊,若是編譯不順利,各類錯誤,你可能一臉懵逼,只能去找小明解決了。這樣無形的就把工做流程搞砸了,你原本就只想要一個A模塊的包,可是你卻幹了一堆不相干的事情,浪費時間。
你可能又想,小明每次將A模塊編譯完成後,使用mvn clean deploy
命令部署到私服,這樣你在編譯你的模塊時,Maven就會自動的去私服下載對應的依賴包。想起來挺美的,可是在Maven中,一樣的版本和一樣的座標就意味着一樣的包,因此,若是你的本地倉庫中已經包含了模塊A的某個版本的包,Maven就不會再對照遠程倉庫進行更新。除非你每次執行Maven命令以前,清除本地倉庫,但這種要求手工干預的作法顯然也是不可取的。
此時你可能又想,小明不斷的修改A模塊的版本號,你也按照小明提供的版本號,修改A模塊的依賴版本。是的,這樣是能夠的,這就須要你和小明頻繁的修改POM,若是有更多的模塊依賴,這個小問題就會變成一個大問題,並且還很容易出錯。
Maven的快照機制就是爲了解決上述問題。在這個開發場景中,小明只須要將模塊A的版本設定爲2.1-SNAPSHOT
,而後發佈到私服中,在發佈的過程當中,Maven會自動爲包打上時間戳。好比上面的2.1-20190412.221213-52
就表示2019年4月12日22點12分13秒的第52次快照。有了這個時間戳,Maven就能隨時找到倉庫中該包2.1-SNAPSHOT
版本最新的文件。當你編譯B模塊時,Maven會自動從倉庫中檢查模塊A模塊的2.1-SNAPSHOT
的最新輸出包,當發現有更新時便進行下載。
基於快照版本機制,在不須要額外手工操做的狀況下,就能完美的解決上述問題。在知道了快照的原理以後,咱們的項目不該該依賴任何快照版本的依賴包,因爲快照版本的不穩定性,這樣的依賴會形成潛在的危險。
若是倉庫X能夠提供倉庫Y存儲的全部內容,那麼就能夠認爲X是Y的一個鏡像。也就是說,任何一個能夠從倉庫Y得到的依賴包,都可以從它的鏡像中獲取。好比http://maven.aliyun.com/nexus/content/groups/public
是阿里提供的中央倉庫的鏡像,因爲地理位置等其它因素,該鏡像每每可以提供比中央倉庫更快的服務。所以,通常狀況下,咱們會配置鏡像來替代中央倉庫。編輯settings.xml文件便可,好比配置阿里提供的鏡像:
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors>
mirrorOf
的值爲central,表示該配置爲中央倉庫的鏡像,任何對於中央倉庫的請求都會轉至該鏡像;id
、name
和url
的配置與通常倉庫配置同樣,表示該鏡像倉庫的惟一標識符、名稱以及地址。
回頭一看,Maven倉庫的知識點這麼多。這篇文章主要以理解性的知識點爲主,不少內容都參考了網上的其它博文。這裏的知識點你不必定在使用Maven的過程當中都會用到,可是理解了,就讓你之後的工做更加駕輕就熟。不求都會,但求上面的內容你都看一遍,心中對Maven倉庫的概念和相關知識點有一個比較全面的理解和認識。全文讀完,用不了十分鐘。用十分鐘學習一個知識點,仍是很是值得的。
果凍想,玩代碼,玩技術!
2019年4月13日,於內蒙古呼和浩特。