|-1-更新內(nèi)容[6.從倉庫解析依賴的機制(重要)]
1Maven倉庫作用
倉庫用來存儲所有項目使用到構(gòu)件,在maven項目需要依賴時就從該倉庫中獲取需要的依賴添加到classpath供其使用。
1.1需求背景
非maven項目如果要使用依賴,在其項目目錄下有一個lib文件夾,用來存放當前項目依賴的構(gòu)件或者架包。這樣就存在一個問題,如果一個電腦上有10個項目,每個項目依賴的架包都有重復的,那么就會存在把相同架包在每個項目的lib目錄下都拷貝一份的情況,當公司需要統(tǒng)一換掉一個架包時就需要把每個項目的該架包都刪掉在重新拷貝。由此可見問題有2個。1是每個項目都有l(wèi)ib文件夾造成磁盤空間浪費。2最重要的是不能統(tǒng)一管理所有的依賴。
maven倉庫就是用來解決上述問題的,所有的maven項目下都沒有l(wèi)ib文件夾,也就是maven項目不再各自存儲其依賴文件,它們只需要聲明這些依賴的坐標,在需要的時候(例如,編譯項目的時候需要將依賴加入到classpath中),Maven會自動根據(jù)坐標到倉庫中找構(gòu)件,并使用它們。
為了實現(xiàn)重用,項目構(gòu)建完畢后生成的構(gòu)件也可以安裝或部署到倉庫中,供其他門項目使用。
2Maven倉庫布局
2.1布局規(guī)則
倉庫一個文件系統(tǒng),里面存放個下載的所有依賴文件,那么這些依賴在倉庫中是按照什么樣規(guī)則存儲布局*的呢?
任何構(gòu)件都有其唯一的坐標,根據(jù)這個坐標可以定義在倉庫中的唯一存儲路徑
路徑規(guī)則:groupId/artifactId/version/artifactId-verson.packaging。
比如:log4j:log4j:1.2.15這一依賴,在倉庫的對應路徑為: log4j/log4j/1.2.15/log4j-1.2.15.jar。
2.2本地倉庫中依賴文件夾中其它文件解釋
log4j-1.2.15.pom:log4j-1.2.15.jar依賴的pom文件,該文件在log4j-1.2.15.jar文件解壓后也能得到,只是名稱為pom.xml。
_remote.repositories:該文件所在的遠程倉庫信息。
log4j-1.2.15.jar.sha1:log4j-1.2.15.jar文件的校驗和文件,log4j-1.2.15.jar文件下載后為了驗證下載內(nèi)容是否完整,需要使用log4j-1.2.15.jar.sha1中的校驗和值來比對。如果下載內(nèi)容不完整(網(wǎng)絡(luò)原因等)maven會作出相應通知。(下面遠程倉庫配置有講解)
log4j-1.2.15.pom.sha1:log4j-1.2.15.pom的校驗和文件。
3倉庫的分類
3.1介紹
倉庫分為兩種,遠程倉庫和本地倉庫,maven根據(jù)坐標尋找構(gòu)件時,會先在本地倉庫查找,本地找不到會到遠程倉庫查找,找到后會下載到本地倉庫,如果本地和遠程倉庫都找不到就會報錯。
本地倉庫在本地計算機上。
遠程倉庫和本地倉庫相對。
中央倉庫是Maven很想自帶的遠程倉庫,它包含了大部分開源構(gòu)件,默認配置下,當本地倉庫找不到構(gòu)件就去遠程倉庫下載,其中的遠程倉庫默認就是中央倉庫。此時需要連接外網(wǎng)下載構(gòu)件,下載構(gòu)件的時間會受網(wǎng)絡(luò)的影響。
私服是一種特殊的遠程倉庫,為了節(jié)省帶寬時間,應該在局域網(wǎng)內(nèi)假設(shè)一個私有的倉庫服務(wù)器,用其代理所有外部的遠程倉庫,內(nèi)部項目在本地找不到時就到私服上下載,因為是公司內(nèi)部網(wǎng)絡(luò)下載起來就好很快,如果私服上沒有,私服就會通過代理去下載。內(nèi)部的項目還能部署到私服上供其他項目使用。
其它公開的遠程倉庫,常見的有JBoss Maven庫和Java.net Maven庫等。
3.2本地倉庫
3.2.1本地倉庫位置
- 本地倉庫默認位置在${user.home}/.m2/repository目錄下。我的用戶名為liang,則本地倉庫地址為C:\Users\liang.m2\repository\,而Linux上的本地倉庫地址為home/liang/.m2/repository/注意Liunx中以點(.)開頭的文件或目錄默認隱藏的,可以使用ls-a命令查看。
3.2.2修改本地倉庫位置
- 如果不喜歡默認位置可以修改,修改本地倉庫位置
3.2.2三種方式添加構(gòu)件到本地倉庫
3.2.2.1從遠程倉庫下載下來。
通過在項目的pom中配置依賴,dependency下載需要的依賴到本地倉庫。
3.2.2.2 通過maven命令安裝maven項目到本體倉庫
- 在某個maven項目根目錄下執(zhí)行:mvn clean install命令就可以把項目以構(gòu)件形式安裝到本地倉庫中。(部署到私服上執(zhí)行mvn clean deploy后面講)
3.2.2.3安裝第三方構(gòu)件到本地倉庫
- 第三方,只是一個jar包,出現(xiàn)這種情況:別人開發(fā)好的一個jar包,但是沒有發(fā)布到maven中央倉庫中,我需要在maven項目中使用,所以,我們可以通過命令將該jar包添加到本地倉庫中,這樣就可以在項目中聲明使用了,聲明一個構(gòu)件當然需要groupId\artifactId、version。
- 需求:把jar:g:\edu.mit.jwi_2.3.3_jdk.jar 安裝到本地倉庫,并且自定義它的gourpId=local.edu.stanford; artifactId=edu.mit.jwi_jdk;version=2.3.3;packaging =jar
- 操作:在命令行中執(zhí)行如下命令即可。詳見:install:install-file
mvn install:install-file -Dfile=g:\edu.mit.jwi_2.3.3_jdk.jar -DgroupId=local.edu.stanford -DartifactId=edu.mit.jwi_jdk -Dversion=2.3.3 -Dpackaging=jar -DpomFile=g:\pom.xml
關(guān)于部署第三方構(gòu)件到Nexus私服倉庫,請查看maven---9使用Nexus創(chuàng)建私服----->5.3手動部署第三方構(gòu)件至Nexus
3.3遠程倉庫
- 遠程倉庫相對本地倉庫,本地倉庫不存在的構(gòu)件才會從遠程倉庫下載,并保存在本地倉庫中。對maven來說,每個用戶只有一個本地倉庫,但可以配置訪問很多遠程倉庫。
3.4中央倉庫
- 由于最原始的本地倉庫是空的,Maven必須知道至少一個可用的遠程倉庫,才能在執(zhí)行maven命令的時候下載需要的構(gòu)件。中央倉庫就是這樣一個默認的遠程倉庫,中央倉庫的信息在超級Pom中配置,所有的maven項目都會繼承超級POM。 超級POM的位置: $M2_HOME/lib/maven-model-builder-3.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>
- 解釋 使用id=central對倉庫進行唯一標識;name倉庫名稱;url倉庫地址;layout=default指定倉庫的布局,default也就是上面提到布局規(guī)則;enabled=false表示不從該中央倉庫下載快照版本的構(gòu)件。
3.5私服
- 私服是一種特殊的遠程倉庫,它是架設(shè)在局域網(wǎng)的倉庫服務(wù),私服代理廣域網(wǎng)上的遠程倉庫,供局域網(wǎng)使用。
3.5.1架設(shè)私服的好處
節(jié)省資金的外網(wǎng)帶寬,利用私服代理外部倉庫之后,對外的重復構(gòu)件下載便得以下手,降低外網(wǎng)帶寬壓力。
加速Maven構(gòu)建。不停地連接請求外部倉庫是什么耗時的,但是maven的一些內(nèi)部機制(如快照更新檢查)要求Maven在執(zhí)行構(gòu)建的時候不停地檢查遠程倉庫數(shù)據(jù)。因此,當項目配置了很多外部遠程倉庫的時候,構(gòu)建速度會降低。使用私服解決這問題,因為Maven只需要檢查局域網(wǎng)內(nèi)私服的數(shù)據(jù)時,構(gòu)建速度便提高。
部署第三方構(gòu)件,當某個構(gòu)件無法從任何一個遠程倉庫獲取怎么辦?比如Oracle的JDBC驅(qū)動由于版權(quán)原因不能發(fā)布到公共倉庫中。建立私服后,便可以將這些構(gòu)件部署到這個內(nèi)部倉庫中,供內(nèi)部Maven項目使用。
提高穩(wěn)定性,增強控制。對于遠程倉庫當外網(wǎng)不可用時,maven構(gòu)建有可能因為依賴沒有下載而不可行,私服后,即使沒有網(wǎng),如果該構(gòu)件只有之前被其它人下載過就會存在私服上,此時我下時就可以不用連接外網(wǎng)直接就可以從私服上下載到。同時私服軟件(nexus)還提供了額外的管理功能。
降低中央倉庫的負荷。
4遠程倉庫配置(包含更新策略)
4.1配置
默認的中央倉庫無法滿足項目需求,可能需要的構(gòu)件在另外一個遠程倉庫,如JBoss Maven倉庫,可以POM中配置該倉庫。
<repositories>
....
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>https://repository.jboss.com/maven2/</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
....
</repositories>
4.1.1解釋
- id要唯一,如果出現(xiàn)重復會覆蓋掉之前的。
- 對于releases的enabled=true表示開啟JBoss倉庫的發(fā)布版本下載支持。根據(jù)以上配置,maven只從JBoss倉庫下載發(fā)布版本的構(gòu)件不會下載快照版本。
- 對于releases和snapshots來說,除了enabled還包含兩個子元素updataPolicy和checksumPolicy
<releases>
<enabled>true</enabled>
<updataPolicy>daily</updataPolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
- updataPolicy:配置maven從遠程倉庫檢查更新的頻率,對同一個版本(如:log4j.1.2.15.jar)的構(gòu)件如果發(fā)現(xiàn)有更新(如:對log4j.1.2.15.jar進行了內(nèi)容修復但是版本都不變)會下載最新的。默認daily-maven每天檢查一次
never-從不檢查;always-每次構(gòu)件都要檢查更新;interval:X -每隔X分鐘檢查一次更新(X為整數(shù))
當然:用戶可以使用參數(shù)-U,強制檢查更新,使用參數(shù)后,maven就會忽略updatePolicy的配置。
至于如何更新請看下面的(6從倉庫解析依賴的機制),其中涉及到從遠程下載maven-metadata.xml文件。 - checksumPolicy:用來配置Maven檢查校驗和文件失敗后的策略。構(gòu)件被部署到maven倉庫中時會同時部署對應的校驗和文件,maven會驗證校驗和文件以確定下載的構(gòu)件是否完整,如果校驗失敗,怎么辦?策略有3中:(默認值)warn-maven會執(zhí)行構(gòu)建時輸出警告信息;fail-maven遇到校驗和錯處就讓構(gòu)建失敗;ignore-使maven完全忽略校驗和錯誤。
4.2遠程倉庫的認證
- 有時候處于安全考慮,需要提供認證信息才能訪問一些遠程倉庫。為了能讓maven訪問倉庫內(nèi)容,就需要配置認證信息,認證信息的配置不會在pom.xml配置,而是在settings.xml中配置,因為pom會被提交到代碼倉庫中供所有成員訪問,而settings.xml一般只放在本機。
- 假設(shè)我在pom.xml中配置id=my-proj的遠程倉庫,需要認證信息,則在settings.xml中配置如下:
<settings>
...
<servers>
<server>
<id>my-proj</id>
<username>repo-user</username>
<password>repo-pwd</password>
</server>
</servers>
...
</settings>
這里的id=my-proj一定要和pom.xml中倉庫的id一致,這是它們之間唯一的聯(lián)系。
settings.xml的servers中就是用來配服務(wù)器授權(quán)信息的,當然不僅可以配置倉庫服務(wù)器認證信息,還可以配置其它的比如tomcat服務(wù)器授權(quán)信息也可以在這里配置。
4.3部署當前maven項目至遠程倉庫
4.3.1需求
- 私服的一個作用是部署公司內(nèi)部生成的構(gòu)件以及一些無法從外部倉庫獲取的構(gòu)件。那么如何把maven項目部署到私服上或者其他的遠程服務(wù)器上呢?
4.3.2操作步驟
步驟-1配置pom.xml
需要編寫pom.xml文件,配置distributionManagement元素。
<distributionManagement>
<repository>
<id>proj-releases</id>
<name>Proj Release Repository</name>
<url>http://192.168.1.100/content/repositories/proj-releases</url>
</repository>
<snapshotRepository>
<id>proj-snapshots</id>
<name>Proj Snapshot Repository</name>
<url>http://192.168.1.100/content/repositories/proj-snapshots</url>
</snapshotRepository>
</distributionManagement>
- distributionManagement包含repository和snapshotRepository子元素,前者表示發(fā)布版本構(gòu)件的倉庫,后者表示快照版本的倉庫。
- id為遠程倉庫的唯一標識,name是為了方便人閱讀,url表示該倉庫的地址。
步驟-2配置settings.xml
- 往倉庫部署構(gòu)件往往需要認證,配置方式如上面所講,只需要配置settings.xml中的server元素。同時其id要與倉庫id匹配。不論部署還是下載構(gòu)件,當需要認證時配置方式一樣。
步驟-3使用部署命令
- 在命令行運行 mvn clean deploy。Maven就會將項目構(gòu)建輸出的構(gòu)件部署到配置對應的遠程倉庫,如果項目版本是快照版本就部署到快照版本倉庫地址,同理發(fā)布版本倉庫地址。
5快照版本
任何一個項目或者構(gòu)件都必須由自己的版本,1.0.0、1.2-alpha-4、2.0、2.1-SNAPSHOT,其中2.1-SNAPSHOT是不穩(wěn)定的快照版本。
5.1需求
小張和李MM負責公司同一個項目的不同模塊,小張負責A模塊,李MM負責B模塊,但是B模塊的開發(fā)過程中依賴A模塊,為了保證快速開發(fā),小張的模塊A內(nèi)容的變化應該盡快的讓李MM獲取到,但是李MM獲取小張模塊A是通過groupId、artifactId、version來配置獲取的,怎樣才能獲取最新的呢?兩人不停的改變版本號? 那么小張和李MM怎么配合開發(fā)呢?
5.2方案
方案1:讓李MM自己簽出模塊A的源代碼進行構(gòu)建,這種方法能夠確保李MM得到模塊A的最新構(gòu)件,不過她不得去自己構(gòu)建A,當構(gòu)建失敗時,她會一頭霧水不得不去找小張解決,效率低。
方案2:小張重復部署模塊A的2.1版供李MM下載。問題:雖然小張能夠保證倉庫中的構(gòu)件是最新的,但是對于maven來說,同樣的版本就是同樣的構(gòu)件,所以李MM本地倉庫包含了A2.1,maven就不會再對倉庫進行更新了,除非執(zhí)行maven命令之前,清除本地倉庫,效率低。
方案3:不停更新版本2.1.1、2.1.2、2.1.3 ....。小張和小麗都需要不停的更新Pom,如果更多模塊依賴A,就會涉及更多pom更改。這就涉及到兩問題:小張更新版本號時要對李MM說一下讓她也更新一下。其次是版本號濫用。
-
方案4(快照):解決上述問題,使用快照機制,該例中,小張只需要將模塊A的版本設(shè)定為2.1-SNAPSHOT,然后發(fā)布到私服中,在發(fā)布過程中maven會自動為構(gòu)件打上時間戳,比如2.1-20161119-105936-12:表示2016年11月19號10點59分36秒第12次修改,有了該時間戳,Maven就能隨時找到該倉庫中該構(gòu)件2.1-SNAPSHOT的最新構(gòu)件。也就是2.1-SNAPSHOT對應了許多帶有不同時間戳的構(gòu)件。李MM這邊配置對于模塊A的2.1-SNAPSHOT版本,當構(gòu)建模塊B時發(fā)現(xiàn)有更新便進行下載,默認情況下,maven每天檢查一次更新(由倉庫配置的updataPolicy控制,上面有講),李MM也可以使用命令行-U參數(shù)強制maven更新,如:mvn clean install-U 。
- 基于快照機制,這樣小張和李MM就不用不斷的修改版本了。小張構(gòu)建成功后發(fā)布到倉庫,李MM不用手工操作,她就可以得到A的最新快照版本構(gòu)件。
5.3使用經(jīng)驗
當項目測試后需要發(fā)布時,將快照版改為發(fā)布版本。如2.1-SNAPSHOT改為2.1,且只對應唯一構(gòu)件,而2.1-SNAPSHOT對應了許多帶有不同時間戳的構(gòu)件。
快照版使用場景 快照版只應該在公司內(nèi)部項目使用,因為項目成員對不同的模塊有清晰的理解和控制。項目不應該依賴第三方的快照版構(gòu)件。那樣存在不受控制和不穩(wěn)定性。
6從倉庫解析依賴的機制(重要)
上一節(jié)介紹了Maven依賴機制,本章闡述了Maven倉庫,這兩者是如何具體聯(lián)系到一起的呢?Maven是根據(jù)怎樣的規(guī)則從倉庫解析并使用依賴構(gòu)件的呢?
6.1解析構(gòu)件步驟
該步驟適用于插件、依賴的解析
- 當依賴范圍是system時候,Maven直接從本地文件解析構(gòu)件。
- 根據(jù)依賴坐標計算倉庫路徑后,先從本地倉庫尋找構(gòu)件,如果發(fā)現(xiàn)則解析成功。
- 本地倉庫沒找到,如果依賴版本(version)是發(fā)布版構(gòu)件,即1.2,2.3等,則遍歷遠程倉庫,發(fā)現(xiàn)后下載并解析使用。
- 如果version是SNAPSHOT版,如:2.1-SNAPSHOT,則基于更新策略(updatepolicy)讀取所有遠程倉庫的元數(shù)據(jù)groupId/artifactId/version/maven-metadata.xml,將其與本地倉庫的對應元數(shù)據(jù)合并后,得到最新快照版本的值,然后基于該值檢查本地倉庫,或者從遠程倉庫下載。(如果最新版還是之前的值就不需要去遠程倉庫下載了)。
注意:這一步因為updatepolicy的原因,可能要求本機能連接到遠程倉庫(遠程倉庫可以是私服或者中央倉庫,一般只有自己的項目會使用SNAPSHOT,所以大多數(shù)是私服) - 如果最后解析得到構(gòu)件版本是時間戳格式的快照,如1.4.1-20161121.121432-121則復制其時間戳格式的文件至非時間戳格式,如SNAPSHOT,并使用該時間戳格式的構(gòu)件。
- 當依賴的version值為RELEASE時(不建議),Maven會基于updatepolicy策略讀取遠程倉庫的元數(shù)據(jù)groupId/artifactId/maven-metadata.xml,將其與本地倉庫相對應元數(shù)據(jù)合并后,計算出最新版本的RELEASE值(穩(wěn)定版),然后基于這個值檢查本地和遠程倉庫,步驟如2和3。
注意:存在潛在問題,如某個依賴的1.1版本與1.2版本可能發(fā)生一些接口變化,從而導致當前Maven項目構(gòu)建失敗,所以依賴的版本最好確定
注:第4步驟在6.2、6.3節(jié)有詳解
6.2解析進一步說明
當構(gòu)件版本version為RELEASE,或為快照版,maven都需要基于倉庫配置的更新策略updatePolicy來檢查更新最新版本,那么更新策略就是上面4.1、4.1.1所講的。(其中的倉庫可以是存放依賴的倉庫也可以是存放插件的倉庫),當構(gòu)件的version有穩(wěn)定版值(如2.1),而且在本地倉庫有該構(gòu)件后,如果執(zhí)行的maven命令沒有加-U參數(shù),那么根據(jù)6.1的解析步驟,在第2步就返回該構(gòu)件,而不會參照updatePolicy去檢查更新。
1.首先通過配置某個遠程倉庫中<releases>、<snapshots>的<enabled>來確定是否支持從該倉庫下載發(fā)布版本和快照版本構(gòu)件的支持,如果不支持,則不會下載相應類型的構(gòu)件(發(fā)布版和快照版)。
2.如果第1步通過,在通過配置<releases>、<snapshots>的<updatePolicy>來配置檢查更新依賴的頻率:每日更新、永遠更新、從不更新、自定義時間間隔更新。如果updatePolicy為“從不更新”則不會檢查遠程倉庫該插件的內(nèi)容是否變化,而是直接使用本地構(gòu)件。 當然可以通過在命令中加入?yún)?shù)-U,強制檢查更新。(使用-U會強制檢查更新pom.xml中所有依賴和插件不管version有沒有值)。
6.3 快照版和穩(wěn)定版解析構(gòu)件詳解
6.3.1解析時機
- 首先maven項目的pom.xml文件中包含該類構(gòu)件,當在項目上執(zhí)行的mvn命令會用到該類構(gòu)件時就會觸發(fā)解析事件。
6.3.2解析說明
- 當version值為RELEASE或為快照版時,通過2步來解析得到構(gòu)件:1.maven需要通過策略來計算得到構(gòu)件版本的值。2.找到值之后就按照常規(guī)的解析步驟解析構(gòu)件:先在本地倉庫找,找不到再到遠程倉庫找。下面就來介紹第1步。
6.3.3步驟1:獲取構(gòu)件版本值
- 先判斷遠程倉庫是否支持相應構(gòu)件(快照版、發(fā)布版)下載,不支持則解析失敗,支持則再判斷updatePolicy指定的更新頻率是否到達,如果更新頻率沒到,則使用上一次更新得到的結(jié)果,該結(jié)果可能是上次成功的結(jié)果也可能是上次解析失敗的結(jié)果。如果前一次解析失敗(網(wǎng)絡(luò)等原因),則這一次解析返回結(jié)果就是上一次失敗原因。如果前一次解析成功,則這一次直接返回上一次解析得到的值。
- 當更新頻率達到后則執(zhí)行步驟2得到具體的構(gòu)件版本值,如下。
6.3.4步驟2:獲取構(gòu)件版本值
當構(gòu)件version=RELEASE情況(不建議這么設(shè)值)
maven會讀取所有遠程倉庫的元數(shù)據(jù)groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元數(shù)據(jù)(本地倉庫元數(shù)據(jù)為為本地最后一次更新該構(gòu)件從遠程倉庫下載下來的文件)合并后,得到最新快照版本的值。
以nekohtml構(gòu)件為例,該構(gòu)件的依賴配置如下:該構(gòu)件來自于中央倉庫,該依賴倉庫不支持快照版本,只支持發(fā)布本而且更新策略為“每天更新一次”。因為我本地配置了id為nexus-mirror的鏡像從私服中下載構(gòu)件。則nekohtml構(gòu)件在本地倉庫中的元數(shù)據(jù)文件名為maven-metadata-nexus-mirror.xml,文件內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
<versioning>
<latest>1.9.22</latest>
<release>1.9.22</release>
<versions>
<version>1.9.7</version>
<version>1.9.8</version>
。。。。。省略其它版本
<version>1.9.21</version>
<version>1.9.22</version>
</versions>
<lastUpdated>20150417210244</lastUpdated>
</versioning>
</metadata>
- 該xml文件列出來倉庫中存在該構(gòu)件的所有版本,同時latest元素指向了這些版本中最新的那個版本(快照版或發(fā)布版),為1.9.22,release元素指向了這些版本中最新發(fā)布版本。由于不支持快照版,所以該文件中沒有快照版本。lastUpdated是構(gòu)件最新更新的時間,該時間是構(gòu)件創(chuàng)建者發(fā)布該構(gòu)件到中央倉庫的時間。
- maven在更新時會從所有遠程倉庫中下載該構(gòu)件的元數(shù)據(jù)到本地,然后和本地的進行合并,就可以得到所有倉庫中該構(gòu)件的最新版本值。獲取構(gòu)件版本值成功。
當構(gòu)件version為快照版情況
maven讀取所有遠程倉庫的元數(shù)據(jù)groupId/artifactId/version/maven-metadata.xml,將其與本地倉庫的對應元數(shù)據(jù)合并后,得到最新快照版本的值,該元數(shù)據(jù)在version目錄下面,而version沒有值時檢查的元數(shù)據(jù)在artifactId目錄下面。
那么maven如何根據(jù)maven-metadata.xml來檢查更新快照版的最新構(gòu)件的版本值的呢?首先明白一個快照版本0.0.1-SNAPSHOT對應多個構(gòu)件,maven就是找出那個最新的構(gòu)件。
下面以iqasweb項目為例,該項目version0.0.1-SNAPSHOT。項目在本地倉庫元數(shù)據(jù)文件為maven-metadata-nexus-snapshots.xml,內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>com.cnu.iqas</groupId>
<artifactId>iqasweb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<snapshot>
<timestamp>20170111.062153</timestamp>
<buildNumber>4</buildNumber>
</snapshot>
<lastUpdated>20170111062153</lastUpdated>
<snapshotVersions>
<snapshotVersion>
<extension>war</extension>
<value>0.0.1-20170111.062153-4</value>
<updated>20170111062153</updated>
</snapshotVersion>
<snapshotVersion>
<extension>pom</extension>
<value>0.0.1-20170111.062153-4</value>
<updated>20170111062153</updated>
</snapshotVersion>
<snapshotVersion>
<classifier>sources</classifier>
<extension>jar</extension>
<value>0.0.1-20170111.062153-4</value>
<updated>20170111062153</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
</metadata>
- 該xml文件的snapshot元素包含的timestamp和buildNumber兩個元素代表了快照的時間戳和構(gòu)建號,即version版本下的第幾次構(gòu)建的,基于這兩個元素可以得到該倉庫中此快照的最新構(gòu)件版本實際為0.0.1-20170111.062153-4。lastUpdated是構(gòu)件最新更新的時間。snapshotVersions標簽中內(nèi)容是構(gòu)件產(chǎn)生的其它文件的版本標識。
在nexus私服中可以看到該版本的構(gòu)件有4個,正好對應4次構(gòu)建。
- maven讀取所有遠程倉庫的元數(shù)據(jù)groupId/artifactId/**version/maven-metadata.xml,將其與本地倉庫的對應元數(shù)據(jù)合并后,得到最新快照版本的值。獲取版本值成功。
6.4常見解析失敗
在根據(jù)6.1的執(zhí)行步驟解析構(gòu)件時難免因為一些出現(xiàn)一些錯誤,常見一個錯誤如下:
-
解析失敗原因
如果執(zhí)行到第3步驟,因為一些原因(比如沒網(wǎng)絡(luò))從遠程倉庫下載構(gòu)件失敗(不管是私服還是中央倉庫),則依賴解析失敗。 - 解析失敗情況演示
<dependency>
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java</artifactId>
<version>3.0.4</version>
</dependency>
第一次解析上面依賴因為沒網(wǎng)絡(luò)執(zhí)行到第3步失敗:
失敗后在本地倉庫產(chǎn)生的文件如下:
docker-java-3.0.4.jar.lastUpdated文件的內(nèi)容如下:
#NOTE: This is an Aether internal implementation file, its format can be changed without prior notice.
#Mon Jan 09 21:21:29 CST 2017
http\://172.19.201.155\:8081/repository/maven-public/.lastUpdated=1483968089340
http\://172.19.201.155\:8081/repository/maven-public/.error=
-
解決
讓本機可以連接到遠程倉庫,在執(zhí)行編譯,結(jié)果還是錯誤,因為maven緩存了上傳執(zhí)行失:
Paste_Image.png
執(zhí)行命令加上-U參數(shù),或者將解析失敗構(gòu)件在本地倉庫中的xxxx.lastupdated文件刪掉,就不會返回緩存了。
7鏡像
- 如果倉庫X可以提供倉庫Y存儲的所有內(nèi)容,那么就可以認為X是Y的一個鏡像。舉個栗子:http://maven.net.cn/content/groups/public/ 是中央倉庫http://repol.maven.org/maven2/ 在中國的鏡像,由于地理位置原因,該鏡像提供的下載服務(wù)更快。因此可以配置maven使用該鏡像來替代中央倉庫,編輯settings.xml。
<settings>
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
| -->
<mirror>
<id>maven.net.cn</id>
<name>one of the central mirrors in China</name>
<url>http://maven.net.cn/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
</settings>
- 該例中mirrorOf為central,表示該配置為中央倉庫的鏡像,任何對于中央倉庫的請求都會轉(zhuǎn)至該鏡像,用戶也可以使用該方法配置其它倉庫的鏡像。另外三個參數(shù)和配置一般遠程倉庫一樣。
- 鏡像一般用在私服上,因為私服代理了任何外部的公共倉庫,因此對于組織內(nèi)部的maven用戶來說,使用一個私服地址就等于使用所有外部倉庫。
- 為滿足復雜需求,maven支持更高級的鏡像配置。
- <mirrorOf>*</mirrorOf> :匹配所有遠程倉庫。
- <mirrorOf>external:*</mirrorOf> :匹配所有遠程倉庫,使用localhost的除外,使用file://協(xié)議的除外。
- <mirrorOf>repo1,repo2</mirrorOf> :匹配倉庫repo1,repo2,多個使用逗號分隔。
- <mirrorOf>*,!repo1</mirrorOf> :匹配所有遠程倉庫,repo1除外。
8倉庫搜索服務(wù)
我們?nèi)绾螌ふ倚枰囊蕾嚕韵率菐讉€公共Maven倉庫搜索服務(wù),都代理了主流的Maven公共倉庫,如中央倉庫、JBoss、java.net等,搜索關(guān)鍵字有:類名、坐標、校驗和搜索等
8.1Sonatype Nexus
8.2Jarvana
8.3MVNborwser
8.4MVNrepository
有什么不懂的一起探討一下吧,我也是在學習的路上。喜歡給我點個贊吧(哈哈),我會繼續(xù)努力的。
注意
- 鏡像配置的地址,一般應該是一個包含了多個倉庫的倉庫組地址,這個倉庫組里面應該包含中央倉庫、自己的release倉庫,自己的snapshot倉庫,第三方release倉庫等。公司的倉庫是個坑。。。,不要配置鏡像。