今天有朋友和我聊天說筆者已經有兩天沒有寫文章了,都去幹嘛了?我很無奈地回答說被maven弄自閉了。到底是什麼樣的問題導致我花了這麼長時間去解決它?這篇文章告訴你。
一、我想要做的事
筆者前幾天一直在看Hotspot提供的tools包的源碼,並試圖去進行了改造和拓展,最後小有成就完成了第一個版本的虛擬機監控API:vmconsole,這不是重點,重點是在後面。我將它打成了jar包,並且想分享出去,讓其他開發者也能使用,第一時間想到的就是Maven,如果我把它發佈到Maven倉庫不就可以了嗎?於是開始筆者便開始了爬坑之路。
筆者在這裏先爲自己的作品打個預廣告,歡迎廣大編程愛好者使用以及提供意見和建議,同時筆者希望能得到你的小星星鼓勵O(∩_∩)O,後續也會有專門的文章介紹該作品。
JVM虛擬機監控API:VmConsole-Api
- Github:https://github.com/tzfun/VmConsole-Api
- API Document:doc.vmconsole.beifengtz.com
二、遇到的問題
這是筆者第一次將自己的項目發佈到Maven倉庫中,其中的步驟都不清楚,於是我就各種谷歌百度,實在解決不了就找其他人求助,簡單的問題成功得以解決,可最關鍵的問題最後還是自己解決的,接下來就拋出我遇到的問題吧,答案以及解決辦法後面會給出。
- 發佈到哪個Maven倉庫?
Maven項目的信息及配置由pom.xml來存儲,其中包含了項目信息、開發者信息、依賴、插件等,如果想要獲取其他人或組織開發的jar包,那麼就要引入我們再熟悉不過的依賴了,依賴需要從倉庫下載,下載流程如下:
- 檢索本地倉庫,如果有該依賴返回成功,否則進入下一步;
- 檢索私有倉庫,如果有該依賴返回成功,否則進入下一步;
- 檢索中央倉庫,如果有該依賴返回成功,否則返回失敗。
本地倉庫是在每個開發者電腦上,一般在c:/user/.m
文件目錄下;私有倉庫是個人或組織建立的倉庫,需要在全局settings.xml中配置倉庫地址;中央倉庫算是整個Maven存儲的核心倉庫,所有開發者都可以在其中獲取資源。那麼這個問題就解決了,爲了讓開發者方便地獲取該依賴,我需要把jar包發佈到中央倉庫。
- 如何將一個非Maven項目發佈到中央倉庫?
這個問題是筆者遇到的主要問題,我的項目並不是Maven項目,網上一大堆的教程全都是Maven項目如何發佈到中央倉庫,如果我的是Maven項目也不至於忙活這麼久,我的項目正是非Maven項目,一個純Java的,其中還包含了jdk的jar包,正因爲jdk提供的這些jar包在Maven倉庫中沒有,所以我無法把我的項目改成Maven項目,其中的很多類必須依託於這些jar包。所以現在的問題就轉換成了如何把已經打包好了的jar包發佈到中央倉庫。
簡述一下我的做法吧,下面會給出完整的步驟,這也是筆者目前爲止想到的唯一的辦法,如果讀者有更好的方法,希望你和我聯繫一下,筆者也學習學習。要傳到中央倉庫還是得需要Maven項目,所以我新建了一個空的Maven項目,然後將jar包先安裝到本地倉庫,在這個空的Maven項目中引入這個jar的本地依賴,再在pom中配置assembly插件把依賴包合併到一個jar包然後發佈(啓發來源於Springboot,因爲Springboot的Maven項目中有配置這個插件),最後將整個項目發佈到nexus中(倉庫管理中心),在引入依賴的時候不能單純的引入這個項目,而是引入項目中合併的那個jar,在依賴中配置classifier即可。
三、完整步驟
接下來貼出我的完整步驟,其中代碼部分有點長,貼出代碼的目的是方便有遇到同樣情況的人粘貼複製內容,讀者大可略過,只看文字或圖片。
1. 註冊sonatype賬號並創建issue
首先需要在https://issues.sonatype.org/secure/Dashboard.jspa註冊賬號,Sonatype通過JIRA來管理OSSRH倉庫。
需要填寫Email, Full Name, Username以及password,其中Username與Password後面的步驟需要用到,請記下來,後面需要用到。
註冊成功之後創建一個issue
- Project:項目默認值,我的選擇是:Community Support - Open Source Project Repository Hosting (OSSRH)
- IssueType:默認值x,我的選擇是:New Project
- Summary:說明,請介紹一下項目
- GroupId:項目id,根據你的網站域名來,我第一次也是在這裏出錯,比如我的github是github.com/tzfun,那麼groupId就是com.github.tzfun。
- ProjectURL:訪問項目的URL,我寫的是github中這個項目的地址。
- SCMurl:訪問項目的URL,我寫的是github倉庫地址。
- 其他的根據提示填寫
填寫完成之後就提交,中間可能你填寫的issue會有問題,需要和客服交流一下,最後出現下面的回覆說明已經創建成功了。現在你就可以往nexus中上傳項目了
2.安裝並配置GPG
發佈到Maven倉庫中的所有文件都要使用GPG簽名,以保障完整性。如果沒有GPG前面的項目無法發佈到中央倉庫,在後面的close階段會被阻止。
IOS系統請下載GPG Suite:https://gpgtools.org/
Windows系統請下載gpg4win:https://www.gpg4win.org/download.html
安裝好了之後你可以通過圖形界面生成祕鑰,也可以通過命令行生成,圖形界面操作簡單易懂就不演示了,下面演示命令行:
- 生成密鑰對:
gpg --gen-key
,此過程會讓你輸入用戶名密碼,用戶名隨便填即可,密碼請務必記住,因爲後面每次部署發佈的時候都會要輸入此密碼; - 查看公鑰id:
gpg --list-keys
,下一步需要用到; - 將公鑰id發佈到GPG祕鑰服務器:
gpg--keyserver hkp://keyserver.ubuntu.com:11371 --send-keys xxxxxxxxxxxxxxxxxxxx
,假設我的公鑰id是xxxxxxxxxxxxxxxxxxxx; - 檢查是否發送成功:
gpg --keyserverhkp://pool.sks-keyservers.net --recv-keys xxxxxxxxxxxxxxxxxxxx
,發佈成功該步驟完成。
3.Maven全局配置
在Maven的根目錄出去找settings.xml
這個配置文件在apache-maven-3.5.3\conf目錄下,打開然後找到servers標籤,添加一個服務,這裏的id用來唯一標識server,後面配置部署的時候會用到,用戶名和密碼是你在第一步註冊的sonatype賬號密碼。因爲此處填寫的是明文,所以請一定注意保管好!被別人拿到了刪庫跑路都不是問題。
<servers>
<server>
<id>oss</id>
<username>Fundebug</username>
<password>passsword</password>
</server>
</servers>
4.項目pom.xml配置
我的做法和網上一大堆的教程做法不同就在於這一步,最關鍵的配置也在這一步。
如果你是一個Maven項目,那麼只需要在正在編寫的項目中的pom.xml進行配置即可,Maven在打包上傳的時候不會把依賴項打包,只會把你的項目代碼打包然後上傳,這些依賴項都是通過你的pom文件進行記錄的,別人引入了你的依賴之後Maven會自動根據你pom的配置進行下載相關包。所以歸根結底部署這一步只會把你的項目打包成jar並上傳到倉庫,依賴項的jar並不會被上傳!
如果你是一個純Java項目,有一些依賴只有class字節碼文件或者其他提供的jar包(即你所需的庫在Maven倉庫中找不到,但是又有相關的字節碼文件或jar包),無法將你的項目改爲Maven項目,也就是和筆者情況一樣,具體操作如下。
- 創建一個新的Maven項目,其中不需要寫任何代碼,也不需要創建任何類,只需要配置pom中項目信息、作者信息、開源協議等信息。
<!-- 組織Id、項目Id、版本號 -->
<groupId>com.github.tzfun</groupId>
<artifactId>vmconsole</artifactId>
<version>1.0.0</version>
<!-- 項目描述 -->
<name>vmconsole</name>
<url>https://github.com/tzfun/VmConsole-Api</url>
<description>An API that makes it easy to monitor virtual machines</description>
<!-- 開源協議 -->
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<!-- 項目地址,這裏我填寫的github -->
<scm>
<url>https://github.com/tzfun/VmConsole-Api</url>
<connection>https://github.com/tzfun/VmConsole-Api.git</connection>
</scm>
<!-- 編碼格式 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 開發者信息 -->
<developers>
<developer>
<name>beifengtz</name>
<id>beifengtz</id>
<email>[email protected]</email>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
</developers>
-
將你的依賴安裝到本地倉庫:
-
如果你有一些class字節碼文件需要打成jar包,很簡單,隨便使用一個壓縮工具,把你的依賴項目工程壓縮成zip格式,注意一定是zip,因爲zip壓縮格式和jar格式是一樣的,打包之後直接把後綴名改成jar即可。
-
如果你只是一些jar包,沒有“散裝”的class字節碼文件,那麼就可以直接進入下一步操作。
-
用Maven命令行將jar包安裝到本地倉庫,命令如下:
mvn install:install-file -Dfile=D:\vmconsoel-api.jar -DgroupId=com.github.tzfun -DartifactId=vmconsole-local -Dversion=1.0.0 -Dpackaging=jar
- – DgroupId和DartifactId構成了該jar包在pom.xml的座標, 對應依賴的DgroupId和DartifactId
- – Dfile表示需要上傳的jar包的絕對路徑
- – Dversion表示版本號
- – Dpackaging 爲安裝文件的種類,這裏是jar
-
-
在pom中添加本地倉庫依賴
執行成功之後本地倉庫就有剛剛那個項目了,接下里把這個依賴添加到pom文件中,這裏的groupId、artifactId以及version和上面命令的內容一致。
<dependencies>
<dependency>
<groupId>com.github.tzfun</groupId>
<artifactId>vmconsole-local</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
- 配置發佈插件和倉庫地址。
一般只需要三個插件即可,但是這裏我多加了一個assembly插件。如果你本身就是Maven項目,不需要將諸多的依賴打包一起上傳(通過pom可以下載依賴,沒必要把文件放到倉庫),所以不可以不加此插件,將這個插件註釋即可。如果你和我情況一樣不是Maven項目,那麼就需要加入這個插件,它的作用是將所有的依賴jar包合併成一個jar包。
因爲這部分內容較多所以我將我的整個pom.xml一起貼出來,不關心此處的讀者可以略過看下文。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 組織Id、項目Id、版本號 -->
<groupId>com.github.tzfun</groupId>
<artifactId>vmconsole</artifactId>
<version>1.0.0</version>
<!-- 項目描述 -->
<name>vmconsole</name>
<url>https://github.com/tzfun/VmConsole-Api</url>
<description>An API that makes it easy to monitor virtual machines</description>
<!-- 開源協議 -->
<licenses>
<license>
<name>Apache 2</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
<comments>A business-friendly OSS license</comments>
</license>
</licenses>
<!-- 項目地址,這裏我填寫的github -->
<scm>
<url>https://github.com/tzfun/VmConsole-Api</url>
<connection>https://github.com/tzfun/VmConsole-Api.git</connection>
</scm>
<!-- 編碼格式 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 開發者信息 -->
<developers>
<developer>
<name>beifengtz</name>
<id>beifengtz</id>
<email>[email protected]</email>
<roles>
<role>Developer</role>
</roles>
<timezone>+8</timezone>
</developer>
</developers>
<!-- 依賴 -->
<dependencies>
<dependency>
<groupId>com.github.tzfun</groupId>
<artifactId>vmconsole-local</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>release</id> <!-- 部署要用到 -->
<build>
<plugins>
<!-- 將其他依賴打包成一個jar的插件 -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- GPG -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>oss</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
</project>
5.發佈到nexus
接下來在pom.xml目錄下執行命令:
mvn clean deploy -P release
其中release不是命令,而是你的pom文件中配置的profile id。在build過程中需要讓你輸入gpg的密碼,輸入第2步安裝並配置GPG的時候的密碼即可。
6.前往nexus管理
登錄倉庫管理網站nexus:https://oss.sonatype.org/#stagingRepositories,這裏的用戶名密碼是第一步sonatype賬號密碼。
選中你上傳的項目,然後先close,等差不多半分鐘後如果成功Release按鈕就會點亮,再點擊Release按鈕即可。注意close和Release過程都有相應的校驗規則,必須全部符合才能通過,按照上面的步驟操作一般是沒有問題的,如果在第4、5部用deploy-file命令來上傳jar包那麼close過程可能會失敗,因爲close過程中javadoc、source、gpg三個缺一不可。
如果Release成功之後等待差不多2小時就可以在中央倉庫搜到自己的項目啦,地址:https://search.maven.org/
7.添加你項目的依賴
如果你原本就是Maven項目那麼倉庫提供的依賴代碼就可以成功引入了。如果你和我一樣從一開始就是非Maven項目,那麼你搜索到的依賴確實是你的那個項目,但是引入卻不會生效,是因爲沒有選擇classifier,進入你的項目查看項目內容可以看出有幾個jar包,你在引入的時候需要選擇是哪個,比如我這裏就是下面的代碼。
<dependency>
<groupId>com.github.tzfun</groupId>
<artifactId>vmconsole</artifactId>
<version>1.0.3</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
四、總結
在不瞭解一個工具運作原理的情況下很難駕馭它,而我這次就是在沒有清楚Maven發佈流程的情況下就開始東弄西弄,所以浪費了很多時間。在中間我嘗試了各種可能的操作,比如deploy-file、反編譯整個jar包上傳、傳到其他私有云(aliyun)、命令行模擬pom等等,最後沒辦法還是得從瞭解其運行機制來想辦法,筆者詳細看了Maven的官方文檔然後瞭解了Maven的幾個生命週期,最後再配合其他框架的插件寫法才解決了此問題。再次驗證了一句話:沒有內功基礎的劍士練不出好劍法。編程最能體現基礎的重要性,理解計算機或語言運作機理才能融匯貫通。
筆者也建立的自己的公衆號啦,平時會分享一些編程知識,歡迎各位大佬支持~
掃碼或微信搜索北風IT之路關注