maven最佳實(shí)踐:maven倉(cāng)庫(kù)

什么是Maven倉(cāng)庫(kù)

在不用Maven的時(shí)候,比如說(shuō)以前我們用Ant構(gòu)建項(xiàng)目身辨,在項(xiàng)目目錄下丐谋,往往會(huì)看到一個(gè)名為/lib的子目錄,那里存放著各類第三方依賴jar文件煌珊,如log4j.jar号俐,junit.jar等等。每建立一個(gè)項(xiàng)目怪瓶,你都需要建立這樣的一個(gè)/lib目錄萧落,然后復(fù)制一對(duì)jar文件践美,這是很明顯的重復(fù)洗贰。重復(fù)永遠(yuǎn)是噩夢(mèng)的起點(diǎn),多個(gè)項(xiàng)目不共用相同的jar文件陨倡,不僅會(huì)造成磁盤資源的浪費(fèi)敛滋,也使得版本的一致性管理變得困難。此外兴革,如果你使用版本管理工具绎晃,如git,你需要將大量的jar文件提交到代碼庫(kù)里杂曲,可是版本管理工具在處理二進(jìn)制文件方面并不出色庶艾。

Maven倉(cāng)庫(kù)就是放置所有JAR文件(WAR,ZIP擎勘,POM等等)的地方咱揍,所有Maven項(xiàng)目可以從同一個(gè)Maven倉(cāng)庫(kù)中獲取自己所需要的依賴JAR,這節(jié)省了磁盤資源棚饵。此外煤裙,由于Maven倉(cāng)庫(kù)中所有的JAR都有其自己的坐標(biāo)掩完,該坐標(biāo)告訴Maven它的組ID,構(gòu)件ID硼砰,版本且蓬,打包方式等等,因此Maven項(xiàng)目可以方便的進(jìn)行依賴版本管理题翰。你也不在需要提交JAR文件到SCM倉(cāng)庫(kù)中恶阴,你可以建立一個(gè)組織層次的Maven倉(cāng)庫(kù),供所有成員使用豹障。

簡(jiǎn)言之存淫,Maven倉(cāng)庫(kù)能幫助我們管理構(gòu)件(主要是JAR)。

本地倉(cāng)庫(kù) vs. 遠(yuǎn)程倉(cāng)庫(kù)

運(yùn)行Maven的時(shí)候沼填,Maven所需要的任何構(gòu)件都是直接從本地倉(cāng)庫(kù)獲取的桅咆。如果本地倉(cāng)庫(kù)沒有,它會(huì)首先嘗試從遠(yuǎn)程倉(cāng)庫(kù)下載構(gòu)件至本地倉(cāng)庫(kù)坞笙,然后再使用本地倉(cāng)庫(kù)的構(gòu)件岩饼。

比如說(shuō),你的項(xiàng)目配置了junit-3.8的依賴薛夜,在你運(yùn)行mvn test 的時(shí)候籍茧,Maven需要使用junit-3.8的jar文件,它首先根據(jù)坐標(biāo)查找本地倉(cāng)庫(kù)梯澜,如果找到寞冯,就直接使用。如果沒有晚伙,Maven會(huì)檢查可用的遠(yuǎn)程倉(cāng)庫(kù)配置吮龄,然后逐個(gè)嘗試這些遠(yuǎn)程倉(cāng)庫(kù)去下載junit-3.8的jar文件,如果遠(yuǎn)程倉(cāng)庫(kù)存在該文件咆疗,Maven會(huì)將其下載到本地倉(cāng)庫(kù)中漓帚,繼而使用。如果嘗試過(guò)所有遠(yuǎn)程倉(cāng)庫(kù)之后午磁,Maven還是沒能夠下載到該文件尝抖,它就會(huì)報(bào)錯(cuò)。

Maven缺省的本地倉(cāng)庫(kù)地址為${user.home}/.m2/repository 迅皇。也就是說(shuō)昧辽,一個(gè)用戶會(huì)對(duì)應(yīng)的擁有一個(gè)本地倉(cāng)庫(kù)。

你也可以自定義本地倉(cāng)庫(kù)的位置登颓,修改${user.home}/.m2/settings.xml

<settings>  
  ...  
  <localRepository>D:\java\repository</localRepository>  
  ...  
</settings>  

你還可以在運(yùn)行時(shí)指定本地倉(cāng)庫(kù)位置:

mvn clean install -Dmaven.repo.local=/home/juven/myrepo/

還有一點(diǎn)需要理解的是搅荞,當(dāng)我們運(yùn)行install的時(shí)候,Maven實(shí)際上是將項(xiàng)目生成的構(gòu)件安裝到了本地倉(cāng)庫(kù),也就是說(shuō)取具,只有install了之后脖隶,其它項(xiàng)目才能使用此項(xiàng)目生成的構(gòu)件。

了解了本地倉(cāng)庫(kù)暇检,接著了解一下Maven缺省的遠(yuǎn)程倉(cāng)庫(kù)产阱,即Maven中央倉(cāng)庫(kù)。

Maven中央倉(cāng)庫(kù)地址:https://mvnrepository.com/
Maven中央倉(cāng)庫(kù)源地址:https://repo.maven.apache.org/maven2/

安裝好Maven之后块仆,我們可以建立一個(gè)簡(jiǎn)單的項(xiàng)目构蹬,配置一些簡(jiǎn)單的依賴,然后運(yùn)行mvn clean install悔据,項(xiàng)目就構(gòu)建好了庄敛。我們沒有手工的去下載任何jar文件,這一切都是因?yàn)镸aven中央倉(cāng)庫(kù)的存在科汗,當(dāng)Maven在本地倉(cāng)庫(kù)找不到需要的jar文件時(shí)藻烤,它會(huì)查找遠(yuǎn)程倉(cāng)庫(kù),而一個(gè)原始的Maven安裝就自帶了一個(gè)遠(yuǎn)程倉(cāng)庫(kù)——Maven中央倉(cāng)庫(kù)头滔。

這個(gè)Maven中央倉(cāng)庫(kù)是在哪里定義的呢怖亭?

  • maven的superpom, 每個(gè)項(xiàng)目都繼承的pom
  • 位置:$M2_HOME/lib/maven-model-builder.jar

在我的機(jī)器上,我安裝了maven-3.6.2坤检,
我可以找到這個(gè)文件:apache-maven-3.6.2\lib\maven-model-builder-3.6.2.jar
打開該文件兴猩,能找到超級(jí)POM:\org\apache\maven\model\pom-4.0.0.xml,如下圖所示:

在這里插入圖片描述

它是所有Maven POM的父POM早歇,所有Maven項(xiàng)目繼承該配置倾芝,你可以在這個(gè)POM中發(fā)現(xiàn)如下配置:

在這里插入圖片描述

關(guān)于遠(yuǎn)程倉(cāng)庫(kù)的配置,下面的小節(jié)我會(huì)詳細(xì)解釋箭跳,這里我們只要知道晨另,中央倉(cāng)庫(kù)的id為central,遠(yuǎn)程url地址為https://repo.maven.apache.org/maven2衅码,它關(guān)閉了snapshot版本構(gòu)件下載的支持拯刁。

在POM中配置遠(yuǎn)程倉(cāng)庫(kù)

前面我們看到超級(jí)POM配置了ID為central的遠(yuǎn)程倉(cāng)庫(kù),我們可以在POM中配置其它的遠(yuǎn)程倉(cāng)庫(kù)逝段。這樣做的原因有很多,比如你有一個(gè)局域網(wǎng)的遠(yuǎn)程倉(cāng)庫(kù)割捅,使用該倉(cāng)庫(kù)能大大提高下載速度奶躯,繼而提高構(gòu)建速度,也有可能你依賴的一個(gè)jar在central中找不到亿驾,它只存在于某個(gè)特定的公共倉(cāng)庫(kù)嘹黔,這樣你也不得不添加那個(gè)遠(yuǎn)程倉(cāng)庫(kù)的配置。
我這里配置一個(gè)指向阿里云的倉(cāng)庫(kù):

<project>  
...  
  <repositories>  
    <repository>
      <id>spring</id>
      <name>maven repository for spring</name>
      <url>https://maven.aliyun.com/repository/spring</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
  </repositories>  
  <pluginRepositories>  
    <pluginRepository>  
      <id>spring</id>
      <name>maven repository for spring</name>
      <url>https://maven.aliyun.com/repository/spring</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </pluginRepository>  
  </pluginRepositories>  
...  
</project>  

我們先看一下<repositories>的配置,你可以在它下面添加多個(gè)<repository> 儡蔓,每個(gè)<repository>都有它唯一的ID郭蕉,一個(gè)描述性的name,以及最重要的喂江,遠(yuǎn)程倉(cāng)庫(kù)的url召锈。此外,<releases><enabled>true</enabled></releases>告訴Maven可以從這個(gè)倉(cāng)庫(kù)下載releases版本的構(gòu)件获询,而<snapshots><enabled>false</enabled></snapshots>告訴Maven不要從這個(gè)倉(cāng)庫(kù)下載snapshot版本的構(gòu)件涨岁。禁止從公共倉(cāng)庫(kù)下載snapshot構(gòu)件是推薦的做法,因?yàn)檫@些構(gòu)件不穩(wěn)定吉嚣,且不受你控制梢薪,你應(yīng)該避免使用。當(dāng)然尝哆,如果你想使用局域網(wǎng)內(nèi)組織內(nèi)部的倉(cāng)庫(kù)秉撇,你可以激活snapshot的支持。
至于<pluginRepositories>秋泄,這是配置Maven從什么地方下載插件構(gòu)件(Maven的所有實(shí)際行為都由其插件完成)畜疾。該元素的內(nèi)部配置和<repository>完全一樣,不再解釋印衔。

在settings.xml中配置遠(yuǎn)程倉(cāng)庫(kù)

我們知道了如何在POM中配置遠(yuǎn)程倉(cāng)庫(kù)啡捶,但考慮這樣的情況:在一個(gè)公司內(nèi)部,同時(shí)進(jìn)行這3個(gè)項(xiàng)目奸焙,而且以后隨著這幾個(gè)項(xiàng)目的結(jié)束瞎暑,越來(lái)越多的項(xiàng)目會(huì)開始;同時(shí)与帆,公司內(nèi)部建立一個(gè)Maven倉(cāng)庫(kù)了赌。我們統(tǒng)一為所有這些項(xiàng)目配置該倉(cāng)庫(kù),于是不得不為每個(gè)項(xiàng)目提供同樣的配置玄糟。問題出現(xiàn)了勿她,這是重復(fù) !

其實(shí)我們可以做到只配置一次阵翎,在哪里配置呢逢并?就是settings.xml。

不過(guò)事情沒有那么簡(jiǎn)單郭卫,不是簡(jiǎn)單的將POM中的<repositories>及<pluginRepositories>元素復(fù)制到settings.xml中就可以砍聊,setting.xml不直接支持 這兩個(gè)元素。但我們還是有一個(gè)并不復(fù)雜的解決方案贰军,就是利用profile玻蝌,如下:

<settings>  
  ...  
  <profiles>  
    <profile>  
      <id>dev</id>  
      <!-- repositories and pluginRepositories here-->  
      <id>spring</id>
      <name>maven repository for spring</name>
      <url>https://maven.aliyun.com/repository/spring</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </profile>  
  </profiles>  
  <activeProfiles>  
    <activeProfile>dev</activeProfile>  
  </activeProfiles>  
  ...  
</settings>  

這里我們定義一個(gè)id為dev的profile,將所有repositories以及pluginRepositories元素放到這個(gè)profile中,然后俯树,使用<activeProfiles>元素自動(dòng)激活該profile帘腹。這樣,你就不用再為每個(gè)POM重復(fù)配置倉(cāng)庫(kù)许饿。

使用profile為settings.xml添加倉(cāng)庫(kù)提供了一種用戶全局范圍的倉(cāng)庫(kù)配置阳欲。

鏡像

如果你的地理位置附近有一個(gè)速度更快的central鏡像,或者你想覆蓋central倉(cāng)庫(kù)配置米辐,或者你想為所有POM使用唯一的一個(gè)遠(yuǎn)程倉(cāng)庫(kù)(這個(gè)遠(yuǎn)程倉(cāng)庫(kù)代理的所有必要的其它倉(cāng)庫(kù))胸完,你可以使用settings.xml中的mirror配置。

以下的mirror配置阿里云的central倉(cāng)庫(kù)覆蓋了Maven自帶的central:

  <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>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->
     <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus aliyun</name>
        <url>https://maven.aliyun.com/repository/central</url>
     </mirror>
  </mirrors>

這里唯一需要解釋的是<mirrorOf>翘贮,這里我們配置central的鏡像赊窥,我們也可以配置一個(gè)所有倉(cāng)庫(kù)的鏡像,以保證該鏡像是Maven唯一使用的倉(cāng)庫(kù):

  <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>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->
     <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>https://maven.aliyun.com/repository/central</url>
     </mirror>
  </mirrors>

分發(fā)構(gòu)件至遠(yuǎn)程倉(cāng)庫(kù)

mvn install 會(huì)將項(xiàng)目生成的構(gòu)件安裝到本地Maven倉(cāng)庫(kù)狸页,mvn deploy 用來(lái)將項(xiàng)目生成的構(gòu)件分發(fā)到遠(yuǎn)程Maven倉(cāng)庫(kù)锨能。本地Maven倉(cāng)庫(kù)的構(gòu)件只能供當(dāng)前用戶使用,在分發(fā)到遠(yuǎn)程Maven倉(cāng)庫(kù)之后芍耘,所有能訪問該倉(cāng)庫(kù)的用戶都能使用你的構(gòu)件址遇。

我們需要配置POM的<distributionManagement>來(lái)指定Maven分發(fā)構(gòu)件的位置,如下:

<project>    
  ...    
  <distributionManagement>    
    <repository>    
      <id>nexus-releases</id>    
      <name>Nexus Release Repository</name>    
      <url>http://127.0.0.1:8080/nexus/content/repositories/releases/</url>    
    </repository>    
    <snapshotRepository>    
      <id>nexus-snapshots</id>    
      <name>Nexus Snapshot Repository</name>    
      <url>http://127.0.0.1:8080/nexus/content/repositories/snapshots/</url>    
    </snapshotRepository>    
  </distributionManagement>    
  ...    
</project>  

Maven區(qū)別對(duì)待release版本的構(gòu)件和snapshot版本的構(gòu)件斋竞,snapshot為開發(fā)過(guò)程中的版本倔约,實(shí)時(shí),但不穩(wěn)定坝初,release版本則比較穩(wěn)定浸剩。Maven會(huì)根據(jù)你項(xiàng)目的版本來(lái)判斷將構(gòu)件分發(fā)到哪個(gè)倉(cāng)庫(kù)。

一般來(lái)說(shuō)鳄袍,分發(fā)構(gòu)件到遠(yuǎn)程倉(cāng)庫(kù)需要認(rèn)證绢要,如果你沒有配置任何認(rèn)證信息,你往往會(huì)得到401錯(cuò)誤拗小。這個(gè)時(shí)候重罪,如下在settings.xml中配置認(rèn)證信息:

<settings>    
  ...    
  <servers>    
    <server>    
      <id>nexus-releases</id>    
      <username>admin</username>    
      <password>admin123</password>    
    </server>    
    <server>    
      <id>nexus-snapshots</id>    
      <username>admin</username>    
      <password>admin123</password>    
    </server>      
  </servers>    
  ...    
</settings> 

需要注意的是,settings.xml中server元素下id的值必須與POM中repository或snapshotRepository下id的值完全一致哀九。將認(rèn)證信息放到settings下而非POM中剿配,是因?yàn)镻OM往往是它人可見的,而settings.xml是本地的勾栗。

參考文章
https://www.cnblogs.com/shengulong/p/11167371.html
https://www.iteye.com/blog/juvenshun-359256

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惨篱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子围俘,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件界牡,死亡現(xiàn)場(chǎng)離奇詭異簿寂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)宿亡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門常遂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人挽荠,你說(shuō)我怎么就攤上這事克胳。” “怎么了圈匆?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵漠另,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我跃赚,道長(zhǎng)笆搓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任纬傲,我火速辦了婚禮满败,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘叹括。我一直安慰自己算墨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布汁雷。 她就那樣靜靜地躺著净嘀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪摔竿。 梳的紋絲不亂的頭發(fā)上面粮,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音继低,去河邊找鬼熬苍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛袁翁,可吹牛的內(nèi)容都是我干的柴底。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼粱胜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼柄驻!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起焙压,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鸿脓,失蹤者是張志新(化名)和其女友劉穎抑钟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體野哭,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡在塔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拨黔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛔溃。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖篱蝇,靈堂內(nèi)的尸體忽然破棺而出贺待,到底是詐尸還是另有隱情,我是刑警寧澤零截,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布麸塞,位于F島的核電站,受9級(jí)特大地震影響瞻润,放射性物質(zhì)發(fā)生泄漏喘垂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一绍撞、第九天 我趴在偏房一處隱蔽的房頂上張望正勒。 院中可真熱鬧,春花似錦傻铣、人聲如沸章贞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鸭限。三九已至,卻和暖如春两踏,著一層夾襖步出監(jiān)牢的瞬間败京,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工梦染, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赡麦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓帕识,卻偏偏與公主長(zhǎng)得像泛粹,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子肮疗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355