Maven倉庫管理之Nexus

不淨之心發表於2013-03-29
[url]http://my.oschina.net/aiguozhe/blog/101537[/url]

我分兩部分來介紹,首先介紹一下Maven的倉庫,然後在說一下如何通過Nexus來建立我們自己的倉庫,以及如何使用。

[color=red][b]Maven 倉庫[/b][/color]
在以前使用Ant的時候,我們會建立一個lib目錄在存放我們的jar包,比如專案所依賴的第三方包,每建立一個專案都要建立一個lib,不停的做copy工作,不僅是對於磁碟的浪費,而且也造成了版本管理上的麻煩。而且我們還需要通過提交到svn上來對lib進行管理,但是svn對於這種二進位制檔案的管理並不出色。

Maven倉庫的初衷就是為了解決這個問題。 maven倉庫是所有常用的第三方依賴包的集中營。這樣所有的Maven專案就可以從這個倉庫中獲取所需要的資源,Maven倉庫中對jar通過Group Id, Atifact Id, version 來管理,所以Maven專案可以很方便的進行依賴管理。你不需要自己來管理這個龐大的資源倉庫,當然你可以建立一個公司層面的倉庫,這個我在這個章節的後面會介紹。

[b] Maven 倉庫的兩個概念:本地倉庫和遠端倉庫[/b]
本地倉庫是遠端倉庫的一個緩衝和子集,當你構建Maven專案的時候,首先會從本地倉庫查詢資源,如果沒有,那麼Maven會從遠端倉庫下載到你本地倉庫。這樣在你下次使用的時候就不需要從遠端下載了。如果你所需要的jar包版本在本地倉庫沒有,而且也不存在於遠端倉庫,Maven在構建的時候會報錯,這種情況可能發生在有些jar包的新版本沒有在Maven倉庫中及時更新。

Maven預設的本地倉庫地址為${user.home}/.m2/repository 。也就是說,一個使用者會對應的擁有一個本地倉庫。當然你可以通過修改${user.home}/.m2/settings.xml 配置這個地址:
<settings>  
...
<localRepository> D:/java/repository</localRepository>
...
</settings>


如果你想讓所有的使用者使用統一的配置,那麼你可以修改${M2_HOME}/conf/setting.xml

還可以通過在執行時指定目錄(不推薦這麼做):
mvn clean install -Dmaven.repo.local=/home/juven/myrepo/


當我們建立一個簡單的Maven專案後(只需要在pom.xml配置好依賴項),執行mvn clean install就可以把專案構建好,maven會自動從中央倉庫下載所需的依賴項(即jar包)。這個中央倉庫定義在${M2_HOME}/lib/maven-2.0.10-uber.jar 裡面。你可以在裡面找到/org/apache/maven/project/pom-4.0.0.xml這個檔案,在這個檔案裡面定義了中央倉庫的地址:
<repositories>   
<repository>
<id> central</id>
<name> Maven Repository Switchboard</name>
<layout> default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled> false</enabled>
</snapshots>
</repository>
</repositories>



[b]在 POM 中配置遠端倉庫[/b]
當某個依賴項存在於第三方的公共倉庫時,我們需要配置其他遠端倉庫呢。下面是在pom.xml裡面配置一個遠端倉庫的例子:
<repositories>  
<repository>
// 其他遠端倉庫
</repository>
<repository>
<id> maven-net-cn</id>
<name> Maven China Mirror</name>
<url> http://maven.net.cn/content/groups/public/</url>
<releases>
<enabled> true</enabled>
</releases>
<snapshots>
<enabled> false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
// 其他maven外掛倉庫
</pluginRepository>
<pluginRepository>
<id> maven-net-cn</id>
<name> Maven China Mirror</name>
<url> http://maven.net.cn/content/groups/public/</url>
<releases>
<enabled> true</enabled>
</releases>
<snapshots>
<enabled> false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

這裡我們可以看到,允許配置多個repository和 plugin repository,其中<releases><enabled>true</enabled></releases>告訴Maven可以從這個倉庫下載releases版本的構件,而<snapshots><enabled>false</enabled></snapshots>告訴Maven不要從這個倉庫下載snapshot版本的構件。


[i]Maven在使用第三方構件和外掛時是分開來配置的,所以如果我們也希望外掛的下載也通過我們的本地倉庫來下載,那麼我們就需要配置pluginRepository.[/i]

[i]之所以不允許從某些倉庫下載snapshot版本,是因為snapshot版本不穩定,但是某些snapshot版本,比如公司內部正在開發的專案, 是必須的[/i]

至於<pluginRepositories>,這是配置Maven從什麼地方下載外掛構件,Maven的所有行為都是通過外掛來完成的。 <pluginRepository>的配置與<repository>類似,這裡就不多說了。

[b] 在 settings.xml 中配置遠端倉庫[/b]
pom.xml的作用範圍限於一個專案, 但一個公司/組織通常不只開發一個專案,那麼為了避免重複配置,那麼我們可以把一些公共配置放在${MAVEN_HOME}/conf/setting.xml(或${user.home}/.m2/setting.xml中。下面是在setting.xml中配置一個遠端倉庫的例子.
<settings>   
<profiles>
<profile>
<!-- 其他profile -->
</profile>
<profile>
<id>myProfiel</id>
<!-- 在這裡加入<repositories>及<pluginRepositories> -->
</profile>
</profiles>
<!-- 宣告哪些profile被啟用,或根據某些條件啟用 -->
<activeProfiles>
<activeProfile>myProfiel</activeProfile>
</activeProfiles>
</settings>


這裡通過<activeProfile>元素來啟用這個profile,這樣我們就可以全域性的使用這個配置,不再需要為每個POM做重複的配置了(也可以針對特定的條件啟用,比如某些profile只有在使用JDK 1.4時才生效)。

在實際的操作過程中,setting.xml最好不要配置遠端倉庫,最好能夠通過nexus建立公司或者組織自己的倉庫,然後把地址指向自己的倉庫,後面我會介紹為什麼要這麼做以及怎麼做。

[b]配置maven倉庫映象[/b]
當你連線中央倉庫時速度很慢,或有些國外的第三方倉庫無法被訪問時,你可以在setting.xml中為這些倉庫指定一個映象來加快下載依賴項的速度。下面是一個配置映象的例子
<settings>   
...
<mirrors>
<mirror>
<!-- 其他映象庫 -->
</mirror>
<mirror>
<id> maven-net-cn</id>
<name> Maven China Mirror</name>
<url> http://maven.net.cn/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
...
</settings>

這裡的 <mirrorOf>必須指定某個<repository>的Id. 如果想為所有的倉庫做映象, 那麼可以改為:<mirrorOf>*</mirrorOf>

[color=red][b]利用 Nexus 來構建企業級 Maven 倉庫[/b][/color]
[b]Nexus簡介[/b]
Nexus是一個Maven倉庫管理器,用來搭建私有倉庫伺服器。建立公司/組織的私有倉庫的的好處是便於管理,節省公網頻寬,利用內網下載依賴項速度快,還有一個非常有用的功能就是能有效管理內部專案的SNAPSHOT版本,實現各個模組間的共享.

[b]安裝 Nexus[/b]
可以從http://nexus.sonatype.org/downloads/ 獲取最新版本的nexus,本文以1.3.4為例進行說明。

Nexus提供了兩種安裝方式,內嵌Jetty的捆綁包(bundle)和WAR包。前者解壓後即可單獨執行,只要系統中安裝了JRE, 後者需要一個Servlet容器來執行.

[b]使用捆綁包安裝[/b]
如果你使用Windows,那麼下載nexus-webapp-1.3. 4-bundle.zip,並將其解壓至任意目錄,如D:/tools,然後轉到D:\tools\nexus-webapp-1.3.4\bin\jsw\indows-x86-32 ,雙擊執行Nexus.bat。 如果你是在linux下安裝,那麼就下載nexus-webapp-1.3. 4 -bundle.tar.gz,解壓後執行nexus.sh。nexus還支援solaris,macos等作業系統。
當你在控制檯看到“Started SelectChannelConnector@0.0.0.0:8081”之後,說明Nexus啟動成功了。 開啟瀏覽器,訪問http://127.0.0.1:8081/nexus,使用管理員的帳號(admin)和密碼(admin123)登入, 會看到如下的頁面:
[img]http://static.oschina.net/uploads/space/2013/0111/105307_V56O_103999.png[/img]

在這裡可以進行管理倉庫,配置Nexus系統,管理任務,管理使用者,角色,許可權,檢視系統的RSS源,管理及檢視系統日誌等操作。

[b] 使用War包安裝[/b]

下載WAR包,然後將其釋出到servlet容器中即可

到此我們已經安裝好Nexus,下面介紹一下Nexus常用的功能和使用方法。

[b]配置中央倉庫[/b]
在左邊選單欄裡選擇Repositories, 會看到如下的介面:
[img]http://static.oschina.net/uploads/img/201301/11121200_EhRy.jpg[/img]


其中右邊欄上半部分列出當前nexus管理的repository,黑體字是型別為group的repository. 這裡簡單介紹下幾種repository的型別:

hosted,本地倉庫。通常我們會部署自己的構件到這一型別的倉庫。比如公司/組織開發的專案
proxy,代理倉庫,它們被用來代理遠端的公共倉庫,如maven中央倉庫或一些第三方公共倉庫。
group,倉庫組,用來合併多個hosted/proxy倉庫,當你的專案希望在多個repository使用依賴項時,無需引用多個倉庫了,只需要引用一個型別為group的repository即可。
Maven central是Maven的中央倉庫,點選它並選擇configuration標籤欄,我們會看到下面的頁面:
[img]http://static.oschina.net/uploads/space/2013/0111/110029_qjba_103999.png[/img]

這裡有幾個配置項是經常用到的:

Override local storage location: 該選項允許配置 Nexus本地倉庫的存放地址,用來覆蓋其預設的存放地址
Remote storage location: 該選項允許配置遠端倉庫的地址。一般為了提高代理速度,你可以將其修改為國內的映象地址。預設值是http://repo1.maven.org/maven2/
Download remote indexes: 該選項配置是否下載遠端索引檔案。 建議配置為true,這樣我們便可以通過nexus的搜尋功能來搜尋我們需要的依賴項。

[b] 新增代理倉庫(proxy)[/b]
nexus預設提供了Maven central這個代理倉庫,如果你需要新增其他代理倉庫,那麼可以點選左邊欄頁面上的Repositories連結,然後在右邊欄頁面上依次點選add -> add proxy repository, 隨後出現以下頁面:
[img]http://static.oschina.net/uploads/space/2013/0111/110632_3bp6_103999.png[/img]

根據提示填寫相關資訊儲存即可。


[b]管理本地倉庫(hosted)[/b]
Nexus預定義了三種本地倉庫,分別是Releases, Snapshots, 3rd Party. 下面分別介紹一下這三種型別倉庫的作用

Releases: 存放穩定版本的構件。比如我們完成了一個版本的下陣列件的開發,就可以把它釋出到這裡。
Snapshots: 存放快照版本的構件。 比如一個下陣列件在完成所有開發和測試工作之前,是不應該釋出到release倉庫的,但可能其他專案只需用到這個元件的某些介面,只要這些介面完成了開發並通過測試,就可以拿來使用, 從而實現多個專案並行開發。
3rd Party: 存放其他第三方構件。你可能會問, 不是有中央倉庫和其他第三方公共倉庫來管理這些依賴項了嗎?沒錯。但由於某些開源專案出現的時間比maven要早,因此他們大都沒有采用maven方式進行構建。 其他還包括包括一些非開源或使用maven 1.x構建的元件. 我們可以把這類元件通通新增到這裡。

建立本地倉庫的方法很簡單。點選Repository皮膚上方的Add按鈕,然後選擇Hosted Repository,然後在下方的配置皮膚中輸入相關資訊。 注意根據自己的需要選擇本地倉庫的型別
[img]http://static.oschina.net/uploads/img/201301/11121200_qGJe.jpg[/img]


[b] 倉庫組(group)[/b]
通過前面介紹我們瞭解到, 可以建立多個代理倉庫和本地倉庫. 但如果沒有倉庫組的概念,那麼當需要引用這些倉庫時, 就需要將他們逐個新增到pom.xml或setting.xml. 倉庫組是為了簡化倉庫的引用而提出的。有了倉庫組的概念, 我們可以把倉庫根據不同目的進行分組,比如把常用的歸到一組或根據訪問許可權分組, 然後直接宣告引用某個倉庫組即可. 下面是pom.xml中宣告引用一個nexus倉庫組的例子:
<repositories> 
<repository>
<id>nexus-public</id>
<url>http://127.0.0.1:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>

可以看到宣告引用一個倉庫組和一個普通的遠端倉庫,配置的寫法完全一樣。

[i]maven本身沒有倉庫組的概念[/i]
Nexus中預設了2個倉庫組, 分別是public repositories和public snapshot repositories. 如圖:
[img]http://static.oschina.net/uploads/space/2013/0111/115632_f4lW_103999.png[/img]

public repository預設包含本地倉庫的Releases, snapshots和3rd party以及代理倉庫的Maven Central. 你可以在Configuration配置頁新增其他倉庫到這個倉庫組。 如果需要,你還可以建立一個倉庫組,方法是點選 Add->Repository Group, 當New Repository Group介面後,填入ID, name 等相關資訊, 然後在右邊Available Repositories 欄裡可以選擇你要新增的倉庫到你新建的倉庫組.
[img]http://static.oschina.net/uploads/space/2013/0111/115717_OQk5_103999.png[/img]



[b]通過 Nexus 搜尋構件[/b]
在開發過程中過程中,我們往往只記得某個構件的大致名字,這時我們可以通過nexus提供的構件搜尋功能查詢該構件的完整配置資訊(groupId,artifactId,version).如果通過nexus搜不到某個的構件,那說明這個構件不在當前nexus所登記的倉庫中,可能需要新增額外的代理倉庫或手工上傳某個構件。

在使用nexus的搜尋功能之前,必須先讓nexus所登記的倉庫建立索引檔案, Nexus預設是不為每個倉庫建立索引檔案的,因為建立像中央倉庫這樣的索引檔案需要耗費比較大的網路頻寬和事件,僅索引檔案就要幾十兆. 要開啟中央倉庫的索引檔案下載功能需要在Maven Central的配置頁中, 把Download Remote Indexes改為true. 如圖:
[img]http://static.oschina.net/uploads/space/2013/0111/115740_hMna_103999.png[/img]

這樣設定之後, Nexus會自動從遠端中央倉庫下載索引檔案, 為了檢驗索引檔案自動下載是否生效,可以切換到Browse標籤頁,如圖:
[img]http://static.oschina.net/uploads/space/2013/0111/115914_4KtG_103999.png[/img]

如果出現類似於以上資料夾,那說明索引檔案已經建立成功.

下面我們試一下搜尋功能, 搜尋欄輸入testing, 查詢結果如下:
[img]http://static.oschina.net/uploads/space/2013/0111/120059_Fgl2_103999.png[/img]

這是模糊查詢的結果,當然如果你知道更多資訊,比如版本號等,你可以使用高階搜尋,點選高階搜尋後,右邊介面會提供集中搜尋方式:keyword, classname, GAV, checksum
[img]http://static.oschina.net/uploads/space/2013/0111/120116_SM2E_103999.png[/img]

比如我們這裡選擇GAV模式. 假設我只知道artifact的名字(如testng)和版本號(如5.8), 其他的我不知道, 那麼就在artifact 和 version處分別輸入testng 和 5.8 , 搜尋結果如下:
[img]http://static.oschina.net/uploads/space/2013/0111/120235_uFmI_103999.png[/img]

如果你不知道知道構件的名稱, 只知道classname, 那麼你也可以通過class name 的方式搜尋,這裡就不再贅述。

當你選中某項搜尋結果, 頁面的下方會出現這個構件的詳細資訊, 並且會列出這個構件的Maven依賴配置, 你可以直接拷貝到你的pom檔案中使用,這是個非常實用的功能:
[img]http://static.oschina.net/uploads/space/2013/0111/120354_qUqO_103999.png[/img]

[color=red][b]在 Maven 中使用Nexus[/b][/color]
到此我們介紹瞭如何安裝和使用Nexus以及其基本配置, 那麼如何在Maven來使用Nexus本地倉庫呢?其實和配置遠端倉庫的方法一樣。下面是在settings.xml中新增了一個nexus本地倉庫的例子:
<profiles> 
...
<profile>
<id>dev</id>
<repositories>
<repository>
<id>nexus</id>
<url>http://127.0.0.1:8081/nexus/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<url>http://127.0.0.1:8081/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
...
</profiles>

<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>

你也可以在pom.xml中宣告引用某個nexus倉庫。

[b]構件部署[/b]
有些時候我們需要部署構件到Nexus的3rd party, 比如我們在中央倉庫找不到我們需要的構件, 我們可以通過Nexus的UI介面來上傳構件:

點選左邊選單欄的 Repositories, 然後點選右邊介面的3rd party, 選擇介面下方的Artifact Upload, 這個時候出現以下介面:
[img]http://static.oschina.net/uploads/space/2013/0111/131940_I6Ph_103999.png[/img]

上傳構件需要兩個步驟,一個是定義檔案的上傳,再就是構件的實體檔案.第一部分定義檔案可以是POM檔案, 這也是比較推薦的方式, 如果沒有pom檔案,可以選擇以引數的形式輸入。第二部分是上傳構件的實體檔案。這裡簡單說一下Classifier和Extension, 這兩個都是選填項. Classifier用來區別同功能的構件用於不同的場景, 比如這個構件是分別針對JDK14和JDK15做了2個功能一樣的Jar, 這個時候你就需要指定這個構件的Classifier為JDK14還是JDK15. Extension是指副檔名,如果不提供,那麼會自動取這個構件的Packaging Type作為副檔名, 比如ear, jar, war 等等. (Packaging Type是在第一步中通過pom檔案或者手工輸入得到的)

剛才說了3rd party的部署, 對於releases 和 snapshots的部署也是一樣的操作過程.

一般我們會通過UI 介面來部署一些缺失的構件。對於自己開發的構件還有另一種簡單的部署方式, 即通過命令mvn deploy進行部署。但使用這種部署方式需要在pom.xml中新增一些配置,比如:
<project>   

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

</project>

這裡告訴Maven當我要釋出release版本或者snapshot版本時,把構建好的成品上傳到哪個伺服器地址。

最後還要在setting.xml裡面配置一個有部署許可權的Nexus的帳號和密碼
<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>

至此 我們就可以通過命令mvn deploy來發布我們專案到本地倉庫了.
[i]這裡我們使用了admin來進行部署,一般建議使用一個具有部署許可權的賬號執行部署操作。[/i]

補充
1、 發現配置了nexus倉庫組之後,下載構件拋異常
0-10-3 下午05時09分43秒: Build error for /com.newyulong.iptv.domain.entity/pom.xml; org.apache.maven.plugin.PluginResolutionException: Plugin org.apache.maven.plugins:maven-resources-plugin:2.4.1 or one of its dependencies could not be resolved: Missing:
----------
1) org.apache.maven.plugins:maven-resources-plugin:maven-plugin:2.4.1

Try downloading the file manually from the project website.

Then, install it using the command:
mvn install:install-file -DgroupId=org.apache.maven.plugins -DartifactId=maven-resources-plugin -Dversion=2.4.1 -Dpackaging=maven-plugin -Dfile=/path/to/file

Alternatively, if you host your own repository you can deploy the file there:
mvn deploy:deploy-file -DgroupId=org.apache.maven.plugins -DartifactId=maven-resources-plugin -Dversion=2.4.1 -Dpackaging=maven-plugin -Dfile=/path/to/file -Durl=[url] -DrepositoryId=[id]

----------
1 required artifact is missing.

for artifact:
org.apache.maven.plugins:maven-resources-plugin:maven-plugin:2.4.1

from the specified remote repositories:
Nexus ([url]http://localhost:8181/nexus/content/groups/public[/url] , releases=true, snapshots=false)

這裡的主要原因是配置nexus裡面的Public Repositories 順序和條件出錯,導致不能下載構件。比如這個public repositories:
[img]http://static.oschina.net/uploads/space/2013/0111/133443_hwI6_103999.gif[/img]

這個是正確的配置順序。其中左邊的是正在使用的定義好的倉庫,右邊的是候選的倉庫。在這個例子中,nexus下載構件的順序是Releases -->Snapshots --> 3rd party --> Maven Central。

好多公司處於安全考慮,要求使用用代理訪問公網,而nexus經常需要往maven repository中心下載東西,因此需要給nexus的倉庫設定代理。

相關文章