前言
在Android開發中,會經常遇到需要將寫好的某個lib用于各個不同的項目中。一般的做法,就是將lib直接導入到項目中。但是假如lib有bug,那么所有使用lib的項目我們都要進去修改lib的bug,這樣即繁瑣,工作量又大。假如我們可以像gralde中添加依賴那樣,直接一句implementation 'xxx'
代碼從maven倉庫中調用lib,那么我們就不用再一個一個項目中去修復lib的bug了,這樣不僅省事了許多,還安全。
正文
一、本地搭建maven私服
- 在
gradle
中添加如下代碼,與android{...}
同級
// 添加 maven 插件
apply plugin: 'maven'
uploadArchives {
repositories {
mavenDeployer {
pom.project {
// 自定義的項目分組
groupId 'com.homeprint.lib'
// 自定義項目名稱
artifactId 'homeprint-core'
// 項目版本號
version '1.0.1'
}
// 自定義本地倉庫路徑,此處是項目根目錄下的 repo 目錄中
repository(url: uri("../repo"))
}
}
}
- 點擊
gradle
右上角的Syc Now
,同步一下項目,然后在右側的項目的gradle
中找到Tasks
中的upload
,雙擊upload
中的uploadArchives
,將項目發布到本地的maven
倉庫中
- 我配置的本地倉庫路徑是項目根目錄的
repo
目錄,所以可以看到在項目根目錄中出現倉庫文件夾
本地maven
4.如何在項目中引用發布的lib?
- 首先在工程的
build.gradle
(是project
的build.gradle
而不是module
的build.gradle
)中添加我們配置的本地倉庫路徑。
(注:build.gradle
中有兩個repositories
,buildscript
中的是用于gradle
本身構建時使用的,allprojects
中的才是給項目依賴使用的,我們在allprojects
的repositories
中添加本地maven
地址)
- 然后在需要使用的
module
中添加依賴implementation 'com.homeprint.lib:homeprint-core:1.0.0'
,依賴的項目名規則為groupId:artfactId:version
,所以我的依賴為com.homeprint.lib:homeprint-core:1.0.0
這樣就完成了,我們就可以肆無忌憚的在需要的項目中引用我們發布的lib啦,但是這個僅限于本地使用,給自己獨立開發時提供方便。如果是團隊開發,大家使用不同的電腦,就不行了。那么團隊開發時,我們想要達到這種效果該怎么做呢?
二、使用Nexus3.x搭建maven私服
1. 下載Nexus3.x
現在Nexus最新版已經是3.x了,個人喜歡使用新版,所以本次我們使用Nexus3.x來搭建maven私服。我們先去官網下載Nexus Repository Manager OSS 3.x,我用的是windows
系統,所以我下載的是windows版本
的
2. Nexus的安裝與配置
-
目前最新版是
3.14.0
,將下載的壓縮包解壓
解壓后的文件
在減壓的文件夾nexus-3.14.0-04-win64
中有兩個文件夾nexus-3.14.0-04
和sonatype-work
。nexus-3.14.0-04
是程序,sonatype-work
是工作目錄,如果以后要備份數據,只要備份sonatype-work
就行。 將
nexus-3.14.0-04-win64\nexus-3.14.0-04\bin
文件夾所在路徑添加到環境變量Path
中,我的路徑是D:\software\nexus\nexus-3.14.0-04-win64\nexus-3.14.0-04\bin
-
配置
nexus-3.14.0-04-win64\nexus-3.14.0-04\etc
目錄下nexus-default.properties
文件
pic_nexus-default.properties
上述配置中有三個字段關注一下,application-host
、application-port
以及nexus-context-path
application-host :是你訪問的nexus服務器的IP,默認為
0.0.0.0
(即只要是本機上的IP,就能連上nexus服務器,詳解點我)。為了安全和屏蔽掉其他IP,我們可以改訪問IP為localhost指向的IP(一般默認指向127.0.0.1
,可以去C:\Windows\System32\drivers\etc
的hosts
文件中查詢localhost指向的IP),改成本機上其他IP也可以application-port:是IP的端口號,默認為
8081
,如果端口號被占用,自行換成其他端口號-
nexus-context-path:上下文對象路徑,默認是沒有的,如果添加了上下文對象路徑,需要在訪問地址(訪問地址:
application-host:application-port
)后面加上下文對象路徑,即訪問地址變為:application-host:application-port/nexus-context-path
以下是個人更改后的字段值,當然如果只想簡單使用,不更改也沒事,可以跳過
application-port=8081
application-host=127.0.0.1
- 打開
CMD
,執行命令nexus.exe /run
- 瀏覽器中輸入:
127.0.0.1:8081
(此處為你配置的application-host:application-port
,如果你也配置了nexus-context-path
,則為application-host:application-port/nexus-context-path
,例:假如我配置nexus-context-path=/test
,瀏覽器中輸入:127.0.0.1:8081/test
),進入nexus管理頁面,至此nexus已經安裝并且啟動成功
nexus入口
3. Nexus的倉庫創建
在創建倉庫前,先介紹一下倉庫的三種存儲類型Release
、Snapshot
和Mixed
,創建倉庫時會使用到
- Release(正式版): 正式版,適合項目穩定后正式發布使用,特性看下面的原理簡介 [important]。
- Snapshot(快照版): 快照版,適合項目在開發調試中使用,特性看下面的原理簡介 [important] 。
- Mixed(混合版): 可包含release和snapshot版本
Release
與Snapshot
的原理簡介:它們的主要區別在于本地獲取這些依賴的機制不同。
- 對于Release版本的項目: 當項目中添加了一個正式版的version為x的依賴時,構建工具在構建項目時會從遠程倉庫中下載這個version為x的依賴到本地倉庫緩存起來,下次再構建項目時,構建工具會從本地倉庫中查找是否存在這個version為x的依賴,存在就不會在去遠程倉庫中拉取。這種特性會導致在團隊開發中,如果你發布一個正式版的項目時,仍然使用的是同一個version,就可能出現其他使用這個version項目的成員根本接收不到項目的最新變更,這是糟糕的,為了生命安全,大家盡量不要這么做。所以,在每次發布正式版項目時,必須更新version。
- 對于Snapshot版本的項目: 當項目中添加了一個快照版的version為x的依賴時,不管本地倉庫中是否存在這個version為x的依賴,構建工具都會嘗試從遠程倉庫中查看這個version為x的依賴是否最新。這樣就能保證團隊開發時,所有使用這個version為x的依賴的項目都能獲取到依賴最新的變更,而且不用不停的迭代依賴的version。最后一還有一點,Snapshot版項目發布時的version一定要以
-SNAPSHOT
結尾,英文字母必須大寫。
下面正式開始倉庫創建流程:
- 先登錄,初始用戶名和密碼分別為
admin
和admin123
- 登錄后,如下圖操作所示,看到有個模塊為
Blob Stores
,這是文件存儲的地方,默認存在default
中,你可以點擊Create blob store
自己創建一個存儲點
文件存儲的地方
這里,我自己創建了名為homeprint
的新的存儲點
新建存儲點
homeprint存儲點 -
創建自己的maven倉庫
創建自己的maven倉庫
選擇要創建的maven倉庫類型 - 可以看到一共有三種maven類型的倉庫供我們選擇
-
hosted(宿主倉庫) :專門存放無法從遠程倉庫中下載的構件或者公司內部自主開發的一些構件。當hosted倉庫找不到目標構件時,并不能從遠程倉庫下載。并且想要將內部開發構件上傳到maven倉庫,三種倉庫中只能使用hosted。
宿主倉庫創建 -
proxy(代理倉庫) : 當用戶向proxy請求一個資源時,proxy會先在本地倉庫中尋找是否有該資源,沒有的話會從遠程倉庫下載,然后返回給用戶;同時會緩存在本地,下次用戶再請求相同資源時,就可以直接在本地中找到并返回給用戶。proxy起到一層緩存與中轉的作用。
proxy代理的遠程倉庫可以配置,這里我選擇阿里云的maven倉庫(http://maven.aliyun.com/nexus/content/groups/public/
,因為在國內比中央倉庫快很多)
(注意:不支持將內部自主研發的項目上傳到proxy上,只能上傳到hosted中,proxy的主要作用只是緩存從遠程倉庫下載的資源和作為中轉站去遠程倉庫下載需要的資源)
代理倉庫創建 -
group(倉庫組) :多個倉庫的聚合體,將你在nexus中想要使用的maven倉庫聚合在一起,對用戶暴露統一的地址,這樣用戶就不需在項目中配置多個maven地址了。(同樣也不支持將內部研發項目上傳到group中,只能發布到hosted)
倉庫組創建
- 倉庫創建完成(不必要三種倉庫都創建,選擇你想創建的就行)。點擊倉庫的
copy
可以拷貝倉庫路徑。
倉庫創建完成
4. 發布項目到maven倉庫
第一種:使用gradle自動發布
在需要發布的module的build.gradle
中加入如下代碼,與在第一種在發布到maven倉庫的實現基本一致
apply plugin: 'maven'
uploadArchives {
configuration = configurations.archives
repositories {
mavenDeployer {
// 倉庫路徑(只能是hosted倉庫)
repository(url: 'http://192.168.10.128:8081/repository/homeprint-hosted/') {
// 你 Nexus 的賬戶密碼
authentication(userName: 'admin', password: 'admin123')
}
pom.project {
version '1.0.1'
artifactId 'homeprint-common'
groupId 'com.homeprint.lib'
description 'xxxxxx'
}
}
}
}
然后在右側的雙擊下圖中的uploadArchives
,即可發布上傳
上傳完成后,可以在倉庫中看到發布的項目
第二種:使用網頁上傳
點擊倉庫的upload component
可以手動上傳,一般現成的jar或者aar文件可以直接選擇手動上傳
5. module中使用發布的項目
在工程的build.gradle
中添加maven
地址
allprojects {
repositories {
maven { url 'http://127.0.0.1:8081/repository/homeprint-group/' }
}
}
在module的build.gradle
中添加依賴
implementation 'com.homeprint.lib:homeprint-common:1.0.0'
三、其他注意事項
1. gradle中如何指定要上傳到maven的文件
// 將項目指定的 _exports 文件夾下的內容打成 jar
task makeJar(type: Jar) {
baseName = "hpauth-exports"
version = "1.0.0"
extension = "jar"
from('build/intermediates/classes/debug/')
from('build/tmp/kotlin-classes/debug/')
include('com/homeprint/module/auth/_exports/**')
destinationDir = file('build/_exports')
}
// 配置需要上傳到 maven 倉庫的文件,即將上面打包的 jar 上傳
artifacts {
archives makeJar
}
// 上傳部分仍然與之前相同
uploadArchives {
repositories {
mavenDeployer {
repository(url: 'http://127.0.0.1:8081/repository/maven-snapshots/') {
authentication(userName: 'admin', password: 'admin123')
}
pom.project {
version '1.0.0-SNAPSHOT'
artifactId 'hpauth-exsppt'
groupId 'com.homeprint.module'
description 'xxxxxxx'
}
}
}
}
2. 關于外部設備訪問Nexus的問題
上述中,一開始我配置的IP地址是127.0.0.1
,此IP地址外部設備是連接不上的,僅能本機訪問。如果要在同一局域網內讓外部設備可以訪問,請更改為能讓外部設備連上的IP地址,例如PC在局域網內被分配到的IPV4地址。詳解點我
3. 關于Nexus初始時的默認倉庫
nexus在一開始就給我們提供了一些默認倉庫
- maven-central:代理倉庫,配置的是maven官方2號倉庫的地址
- maven-public:倉庫組
- maven-releases:宿主倉庫,倉庫的存儲類型為Release
- maven-snapshot:宿主倉庫,倉庫的存儲類型為Snapshot
上述內容中已經對這些倉庫的類型介紹過,就不在多說了。這些默認倉庫我們是可以直接使用的,基本已經滿足我們所有的需求,所以如果不創建倉庫,可以直接使用默認倉庫。
4. Android開發中常用的maven代理地址
- 阿里云:http://maven.aliyun.com/nexus/content/groups/public/
- google:https://dl.google.com/dl/android/maven2/
- jcenter:https://jcenter.bintray.com/
- mavenCentral:https://repo.maven.apache.org/maven2/
- jitpack:https://jitpack.io
以上幾個基本就是android開發中常用的幾個maven倉庫了,其中阿里云是國內倉庫,其他是國外倉庫。國內倉庫的優勢在于下載速度快,畢竟祖國偉大的網絡對于國外的網絡不怎么友好。但是國內倉庫可能更新會比國外倉庫慢一點。出于以上考慮,我們可以將以上倉庫都集成在group倉庫組中,一定要將阿里云放在其他國外maven倉庫的上面,因為訪問倉庫時的順序是從上往下訪問的,這樣就既有了國內倉庫的速度,又可以在國內倉庫沒有資源時,去國外倉庫獲取到資源。
5. Nexus中用戶的權限管理
團隊開發的時候,為了避免散發超級管理員權限,可以根據每個成員的實際情況,給他們配置用戶角色和權限。
-
Security -> Privileges: 所有的權限都放在了這里
權限大全 -
Security -> Roles: 角色管理界面,可在此界面創建角色
創建角色
角色權限 -
Security -> Users: 用戶管理界面,可在此界面創建用戶
創建用戶
用戶權限 -
Security -> Anonymous: 匿名用戶管理界面(即游客管理),這里有個注意的地方,如下圖中,有個
Allow anonymous users to access the server
,游客默認是有瀏覽
和讀取倉庫
的權限的,如果取消勾選,則游客沒有任何權限。
游客權限1
游客權限2
6. 如何從Nexus中下載jar包或者aar包
四、如何實現在外網中訪問自己的maven倉庫
- 將項目上傳到
Github
、碼云
或者類似的管理平臺中,通過jitpack
發布(最簡單的方式) - 將項目發布到
jcenter
或者mavenCentral
中,這個比第一種復雜一些,如果要使用jcenter
發布,可以使用bintray-release
插件 - 將
Nexus
部署到阿里云或者其他云服務器中,這時使用的版本不再是Windows
版而是Unix
版 - 以上都是常用的方法,因為時間關系就不再詳細介紹了,大家可以自行百度。最后介紹一種取巧的方法,就是找一些可以將內網IP映射到外網訪問的小工具,比如
nat123
、花生殼
之類的,這里我用的是windows_386
,一共就三個文件
windows_386
其中a.bat
是運行文件,里面就一行代碼如下:
ngrok -config=ngrok.cfg -subdomain my 8080
其中my
為域名的前綴,8080
為端口號,這兩樣是可以根據需要,自行修改的。雙擊a.bat
文件開始運行程序,結果如下:
ngrok (Ctrl+C to quit)
Tunnel Status online
Version 1.7/1.7
Forwarding http://my.tunnel.qydev.com -> 127.0.0.1:8080
Forwarding https://my.tunnel.qydev.com -> 127.0.0.1:8080
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
當 Tunnel Status
為online
時,代表已經將內網IP映射到公網上,映射的IP為127.0.0.1
(不可變),端口號為你在a.bat
中配置的端口號,此處為8080
(可配置)。與IP綁定的域名為my.tunnel.qydev.com
,其中前綴my
即為你在a.bat
中配置的前綴。這樣你在瀏覽器中輸入my.tunnel.qydev.com
就可以連上本機的127.0.0.1:8080
。然后,將nexus的IP和端口號分別配置為127.0.0.1
和8080
就可以在外網訪問到本機上的Nexus了。這種方式很簡單,成本低,但是訪問速度有點慢,但是誰還沒有個不在公司coding的時候,這時候就可以提供點便利了。