Maven 倉庫

在 Maven 的術(shù)語中,倉庫是一個位置(place)。
Maven 倉庫是項目中依賴的第三方庫,這個庫所在的位置叫做倉庫。
在 Maven 中,任何一個依賴、插件或者項目構(gòu)建的輸出,都可以稱之為構(gòu)件。
Maven 倉庫能幫助我們管理構(gòu)件(主要是JAR),它就是放置所有JAR文件(WAR,ZIP,POM等等)的地方。
Maven 倉庫有三種類型:

  • 本地(local)
  • 中央(central)
  • 遠程(remote)

本地倉庫

Maven一個很突出的功能就是jar包管理,一旦工程需要依賴哪些jar包,只需要在Maven的pom.xml配置一下,該jar包就會自動引入工程目錄。初次聽來會覺得很神奇,下面我們來探究一下它的實現(xiàn)原理。

首先,這些jar包肯定不是沒爹沒娘的孩子,它們有來處,也有去處。集中存儲這些jar包(還有插件等)的地方被稱之為倉庫(Repository)。
不管這些jar包從哪里來的,必須存儲在自己的電腦里之后,你的工程才能引用它們。類似于電腦里有個客棧,專門款待這些遠道而來的客人,這個客棧就叫做本地倉庫。

比如,工程中需要依賴spring-core這個jar包,在pom.xml中聲明之后,maven會首先在本地倉庫中找,如果找到了很好辦,自動引入工程的依賴lib庫即可。可是,萬一找不到呢?實際上這種情況經(jīng)常發(fā)生,尤其初次使用maven的時候,本地倉庫肯定是空無一物的,這時候就要靠maven大展神通,去遠程倉庫去下載。

默認情況下,不管Linux還是 Windows,每個用戶在自己的用戶目錄下都有一個路徑名為 .m2/respository/ 的倉庫目錄。
Maven 本地倉庫默認被創(chuàng)建在 用戶目錄下。要修改默認位置,在 Maven安裝目錄中的 conf文件夾下的 settings.xml 文件中定義另一個路徑。

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 
   http://maven.apache.org/xsd/settings-1.0.0.xsd">
      <localRepository>C:/MyLocalRepository</localRepository>
</settings>

中央倉庫

Maven 中央倉庫是由 Maven 社區(qū)提供的倉庫,其中包含了大量常用的庫。

中央倉庫包含了絕大多數(shù)流行的開源Java構(gòu)件,以及源碼、作者信息、SCM、信息、許可證信息等。一般來說,簡單的Java項目依賴的構(gòu)件都可以在這里下載到。

中央倉庫的關(guān)鍵概念:

  • 這個倉庫由 Maven 社區(qū)管理。
  • 不需要配置。
  • 需要通過網(wǎng)絡才能訪問。

要瀏覽中央倉庫的內(nèi)容,maven 社區(qū)提供了一個 URL:http://search.maven.org/#browse。使用這個倉庫,開發(fā)人員可以搜索所有可以獲取的代碼庫。

遠程倉庫

如果 Maven 在中央倉庫中也找不到依賴的文件,它會停止構(gòu)建過程并輸出錯誤信息到控制臺。為避免這種情況,Maven 提供了遠程倉庫的概念,它是開發(fā)人員自己定制倉庫,包含了所需要的代碼庫或者其他工程中用到的 jar 文件。

一般來講,公司都會通過自己的私有服務器在局域網(wǎng)內(nèi)架設一個倉庫代理。私服可以看作一種特殊的遠程倉庫,代理廣域網(wǎng)上的遠程倉庫,供局域網(wǎng)內(nèi)的Maven用戶使用。當Maven需要下載構(gòu)件的時候,先從私服請求,如果私服上不存在該構(gòu)件,則從外部的遠程倉庫下載,緩存在私服上之后,再為Maven的下載請求提供服務。


Maven 遠程倉庫

Maven私服有很多好處:

  • 可以把公司的私有jar包,以及無法從外部倉庫下載到的構(gòu)件上傳到私服上,供公司內(nèi)部使用;

  • 節(jié)省自己的外網(wǎng)帶寬:減少重復請求造成的外網(wǎng)帶寬消耗;

  • 加速Maven構(gòu)建:如果項目配置了很多外部遠程倉庫的時候,構(gòu)建速度就會大大降低;

  • 提高穩(wěn)定性,增強控制:Internet不穩(wěn)定的時候,maven構(gòu)建也會變的不穩(wěn)定,一些私服軟件還提供了其他的功能

當前主流的maven私服有Apache的Archiva、JFrog的Artifactory以及Sonatype的Nexus。

上面提到的中央倉庫、中央倉庫的鏡像倉庫、其他公共倉庫、私服都屬于遠程倉庫的范疇。

Maven 依賴搜索順序

當我們執(zhí)行 Maven 構(gòu)建命令時,Maven 開始按照以下順序查找依賴的庫:

1.在本地倉庫中搜索,如果找不到,執(zhí)行步驟 2,如果找到了則執(zhí)行其他操作。
2.在中央倉庫中搜索,如果找不到,并且有一個或多個遠程倉庫已經(jīng)設置,則執(zhí)行步驟 4,如果找到了則下載到本地倉庫中已被將來引用。
3.如果遠程倉庫沒有被設置,Maven 將簡單的停滯處理并拋出錯誤(無法找到依賴的文件)。
4.在一個或多個遠程倉庫中搜索依賴的文件,如果找到則下載到本地倉庫已被將來引用,否則 Maven 將停止處理并拋出錯誤(無法找到依賴的文件)。

倉庫的配置

倉庫配置要做兩件事,一是告訴maven你的本地倉庫在哪里,二是你的遠程倉庫在哪里。

顧名思義,setting.xm的第一個節(jié)點<localRepository>就是配置本地倉庫的地方,不用贅言。

遠程倉庫的配置有些復雜,因為會涉及很多附屬特性。下面以一切從實際出發(fā),看看使用私服的情況下如何配置遠程倉庫。稍微像樣的公司都會建立自己的私服,如果一個公司連自己的私服都沒有(別管是因為買不起服務器還是技術(shù)上做不到),你可以考慮一下跳槽的問題了。

現(xiàn)在最流行的maven倉庫管理器就是大名鼎鼎的Nexus(發(fā)音[?n?ks?s],英文中代表“中心、魔樞”的意思),它極大地簡化了自己內(nèi)部倉庫的維護和外部倉庫的訪問。利用Nexus可以只在一個地方就能夠完全控制訪問和部署在你所維護倉庫中的每個Artifact。Nexus是一套“開箱即用”的系統(tǒng)不需要數(shù)據(jù)庫,它使用文件系統(tǒng)加Lucene來組織數(shù)據(jù)。

至于Nexus怎么部署,怎么維護倉庫,作為開發(fā)人員是不需要關(guān)心的,只需要把Nexus私服的局域網(wǎng)地址寫入maven的本地配置文件即可。具體的配置方法如下:

1、設置鏡像

<mirrors>
  <mirror>
       <!--該鏡像的唯一標識符。id用來區(qū)分不同的mirror元素。 -->
       <id>nexus</id>
       <!-- 鏡像名,起注解作用,應做到見文知意??梢圆慌渲? -->
       <name>Human Readable Name </name>
       <!--  所有倉庫的構(gòu)件都要從鏡像下載  -->
       <mirrorOf>*</mirrorOf>
       <!-- 私服的局域網(wǎng)地址-->
       <url>http://192.168.0.1:8081/nexus/content/groups/public/</url> 
  </mirror>
</mirrors>

節(jié)點<mirrors>下面可以配置多個鏡像,<mirrorOf>用于指明是哪個倉庫的鏡像,上例中使用通配符 * 表明該私服是所有倉庫的鏡像,不管本地使用了多少種遠程倉庫,需要下載構(gòu)件時都會從私服請求。

如果只想將私服設置成某一個遠程倉庫的鏡像,使用<mirrorOf>指定該遠程倉庫的ID即可。

2、設置遠程倉庫
遠程倉庫的設置是在<profile>節(jié)點下面:

<repositories>
<repository>
    
   <!--倉庫唯一標識 -->
  <id>repoId </id>
    
   <!--遠程倉庫名稱  -->
  <name>repoName</name>
    
<!--遠程倉庫URL,如果該倉庫配置了鏡像,這里的URL就沒有意義了,因為任何下載請求都會交由鏡像倉庫處理,前提是鏡像(也就是設置好的私服)需要確保該遠程倉庫里的任何構(gòu)件都能通過它下載到  -->
  <url>http://……</url>
 
   <!--如何處理遠程倉庫里發(fā)布版本的下載 -->
  <releases>
      
      <!--true或者false表示該倉庫是否為下載某種類型構(gòu)件(發(fā)布版,快照版)開啟。   -->
    <enabled>false</enabled>
      
      <!-- 該元素指定更新發(fā)生的頻率。Maven會比較本地POM和遠程POM的時間戳。這里的選項是:-->
      <!-- always(一直),daily(默認,每日),interval:X(這里X是以分鐘為單位的時間間隔),或者never(從不)。  -->
    <updatePolicy>always</updatePolicy>
      
      <!--當Maven驗證構(gòu)件校驗文件失敗時該怎么做:-->
      <!--ignore(忽略),fail(失?。?,或者warn(警告)。 -->
    <checksumPolicy>warn</checksumPolicy>
         
  </releases>
    
   <!--如何處理遠程倉庫里快照版本的下載,與發(fā)布版的配置類似 -->
  <snapshots>     
    <enabled/>
    <updatePolicy/>
    <checksumPolicy/>      
  </snapshots>
      
</repository>    
</repositories>

可以配置多個遠程倉庫,用<id>加以區(qū)分。

除此之外,還有一個與<repositories>并列存在<pluginRepositories>節(jié)點,用來配置插件的遠程倉庫。

倉庫主要存儲兩種構(gòu)件。第一種構(gòu)件被用作其它構(gòu)件的依賴,最常見的就是各類jar包。這是中央倉庫中存儲的大部分構(gòu)件類型。另外一種構(gòu)件類型是插件,Maven插件是一種特殊類型的構(gòu)件。由于這個原因,插件倉庫獨立于其它倉庫。<pluginRepositories>節(jié)點與<repositories>節(jié)點除了根節(jié)點的名字不一樣,子元素的結(jié)構(gòu)與配置方法完全一樣:

<pluginRepositories>
      <pluginRepository>
 
             <id />
             <name />
             <url />
 
             <releases>
                    <enabled />
                    <updatePolicy />
                    <checksumPolicy />
             </releases>
                  
             <snapshots>
                    <enabled />
                    <updatePolicy />
                    <checksumPolicy />
             </snapshots>     
 
      </pluginRepository>             
</pluginRepositories>

遠程倉庫有releasessnapshots兩組配置,POM就可以在每個單獨的倉庫中,為每種類型的構(gòu)件采取不同的策略。例如,有時候會只為開發(fā)目的開啟對快照版本下載的支持,就需要把<releases>``中的<enabled >設為false,而<snapshots>中的<enabled >設為true```。

由于遠程倉庫的配置是掛在<profile>節(jié)點下面,如果配置有多個<profile>節(jié)點,那么就可能有多種遠程倉庫的設置方案,該方案是否生效是由它的父節(jié)點<profile>是否被激活決定的。

3、設置發(fā)布權(quán)限
私服的作用除了可以給全公司的人提供maven構(gòu)件的下載,還有一個非常重要的功能,就是開發(fā)者之間的資源共享。

一個大的項目往往是分模塊進行開發(fā)的,各個模塊之間存在依賴關(guān)系,比如一個交易系統(tǒng),分為下單模塊、支付模塊、購物車模塊等?,F(xiàn)在開發(fā)下單模塊的同學需要調(diào)用支付模塊中的接口來完成支付功能,就需要將支付模塊的某些jar包引入本地工程,才能調(diào)用它的接口;同時,開發(fā)購物車模塊的同學需要調(diào)用下單模塊的接口,來完成下單功能,他就需要依賴下單模塊的某些jar包。這三個模塊都在持續(xù)開發(fā)中,不可能將各自的源碼傳來傳去支持對方的依賴。

解決的方式是這樣,每個模塊完成了某個階段性的功能,都會將提供對外服務的接口打成jar包,傳到公司的私服當中,誰要使用該模塊的功能,只需要在pom.xml文件中聲明一下,maven就會像下載其他jar包那樣把它引入你的工程。

在開發(fā)過程中,在pom中聲明的構(gòu)件版本一般是快照版:

<dependency>
      <groupId>com.yourCompany.trade</groupId>
      <artifactId>trade-pay</artifactId>
      <version>1.0.2-SNAPSHOT</version>
</dependency>

各個模塊會不斷的上傳新的jar包,如果本地項目依賴的是快照版,那么maven一旦發(fā)現(xiàn)該jar包有新的發(fā)布,就會將它下載下來替代以前的舊版本。比如,支付模塊在測試的時候發(fā)現(xiàn)有個bug,修復了一下,然后將快照版發(fā)布到私服。而你只需要專注于下單模塊的開發(fā),所依賴的支付模塊的更新由maven處理,不需要關(guān)心。一旦你開發(fā)的模塊修復了一個bug,或者添加了一個新功能等修改,只需要將發(fā)布一次快照版本到私服即可,誰需要依賴你的接口誰自然會去私服下載,你也不用關(guān)心。
一般私服建立完畢之后不需要認證就可以訪問,但是風險會很大,這時就需要使用setting.xml中的servers元素了。需要注意的是,配置私服的信息是在pom文件中,但是認證信息則是在setting.xml中,這是因為pom文件往往是被提交到代碼倉庫中供所有成員訪問的,而setting.xml是存放在本地的,這樣是安全的。

settings.xml中,配置具有發(fā)布發(fā)布版本和快照版本權(quán)限的用戶:

server配置

上面的id是server的id,不是用戶登陸的id,該id與distributionManagement中repository元素的id相匹配。maven是根據(jù)pom中的repository和distributionMnagement元素來找到匹配的發(fā)布地址:


項目配置

注意:pom中的id必須與setting.xml中配置好的id一致。

然后運行maven cleandeploy命令,將自己開發(fā)的構(gòu)件部署在私服上供組織內(nèi)其他用戶使用(maven clean deploy和maven clean install的區(qū)別:deploy是將該構(gòu)件部署在私服中,而install是將構(gòu)件存入自己的本地倉庫中)。

在這里有人可能會有一個疑問,所有的倉庫設置不是已經(jīng)在setting.xml中配置好了嗎,為什么在pom的發(fā)布管理節(jié)點當中還要配置一個url?

Setting.xml中配置的是你從哪里下載構(gòu)件,而這里配置的是你要將構(gòu)件發(fā)布到哪里。有時候可能下載用的倉庫與上傳用的倉庫是兩個地址,但是絕大多數(shù)情況下,兩者都是由私服充當,就是說兩者是同一個地址。

補充:
Maven 倉庫默認在國外, 國內(nèi)使用難免很慢,我們可以更換為阿里云的倉庫。
第一步:修改 maven 根目錄下的 conf 文件夾中的 setting.xml 文件,在 mirrors 節(jié)點上,添加內(nèi)容如下:

<mirrors>
  <mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    <mirrorOf>central</mirrorOf>        
  </mirror>
</mirrors>

第二步: pom.xml文件里添加:

<repositories>  
     <repository>  
           <id>alimaven</id>  
           <name>aliyun maven</name>  
           <url>http://maven.aliyun.com/nexus/content/groups/public/</url>  
           <releases>  
               <enabled>true</enabled>  
           </releases>  
           <snapshots>  
               <enabled>false</enabled>  
           </snapshots>  
     </repository>  
</repositories>

Maven 的 Snapshot 版本與 Release 版本
1、Snapshot 版本代表不穩(wěn)定、尚處于開發(fā)中的版本。
2、Release 版本則代表穩(wěn)定的版本。
3、什么情況下該用 SNAPSHOT?
協(xié)同開發(fā)時,如果 A 依賴構(gòu)件 B,由于 B 會更新,B 應該使用 SNAPSHOT 來標識自己。這種做法的必要性可以反證如下:

  • a. 如果 B 不用 SNAPSHOT,而是每次更新后都使用一個穩(wěn)定的版本,那版本號就會升得太快,每天一升甚至每個小時一升,這就是對版本號的濫用。
  • b.如果 B 不用 SNAPSHOT, 但一直使用一個單一的 Release 版本號,那當 B 更新后,A 可能并不會接受到更新。因為 A 所使用的 repository 一般不會頻繁更新 release 版本的緩存(即本地 repository),所以B以不換版本號的方式更新后,A在拿B時發(fā)現(xiàn)本地已有這個版本,就不會去遠程Repository下載最新的 B

4、 不用 Release 版本,在所有地方都用 SNAPSHOT 版本行不行?
不行。正式環(huán)境中不得使用 snapshot 版本的庫。 比如說,今天你依賴某個 snapshot 版本的第三方庫成功構(gòu)建了自己的應用,明天再構(gòu)建時可能就會失敗,因為今晚第三方可能已經(jīng)更新了它的 snapshot 庫。你再次構(gòu)建時,Maven 會去遠程 repository 下載 snapshot 的最新版本,你構(gòu)建時用的庫就是新的 jar 文件了,這時正確性就很難保證了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容

  • |-1-更新內(nèi)容[6.從倉庫解析依賴的機制(重要)] 1Maven倉庫作用 倉庫用來存儲所有項目使用到構(gòu)件,在ma...
    zlcook閱讀 6,137評論 0 25
  • 在Maven世界中,依賴、插件、項目構(gòu)建完成后輸出的jar包都可以看作是一個構(gòu)件,任何一個構(gòu)件都有一組坐標唯一標識...
    SonyaBaby閱讀 624評論 0 0
  • 簡介 概述 Maven 是一個項目管理和整合工具 Maven 為開發(fā)者提供了一套完整的構(gòu)建生命周期框架 Maven...
    閩越布衣閱讀 4,337評論 6 39
  • 這幾天電影院都被《蝙蝠俠大戰(zhàn)超人》轟炸了。這部全世界矚目的超級英雄電影打著兩位英雄相愛相殺的幌子,騙了一大堆路人。...
    電影探照燈閱讀 377評論 0 0
  • 一個人的一生中總會遇到這樣的時候,一個人的戰(zhàn)爭。在這種時候你的內(nèi)心已經(jīng)兵荒馬亂天翻地覆了,可在別人看來你只是比別人...
    暖暖陽光520閱讀 843評論 2 1