記一次非Maven項目發佈到中央倉庫爬過的坑!

今天有朋友和我聊天說筆者已經有兩天沒有寫文章了,都去幹嘛了?我很無奈地回答說被maven弄自閉了。到底是什麼樣的問題導致我花了這麼長時間去解決它?這篇文章告訴你。

一、我想要做的事

筆者前幾天一直在看Hotspot提供的tools包的源碼,並試圖去進行了改造和拓展,最後小有成就完成了第一個版本的虛擬機監控API:vmconsole,這不是重點,重點是在後面。我將它打成了jar包,並且想分享出去,讓其他開發者也能使用,第一時間想到的就是Maven,如果我把它發佈到Maven倉庫不就可以了嗎?於是開始筆者便開始了爬坑之路。

筆者在這裏先爲自己的作品打個預廣告,歡迎廣大編程愛好者使用以及提供意見和建議,同時筆者希望能得到你的小星星鼓勵O(∩_∩)O,後續也會有專門的文章介紹該作品。

JVM虛擬機監控API:VmConsole-Api

二、遇到的問題

這是筆者第一次將自己的項目發佈到Maven倉庫中,其中的步驟都不清楚,於是我就各種谷歌百度,實在解決不了就找其他人求助,簡單的問題成功得以解決,可最關鍵的問題最後還是自己解決的,接下來就拋出我遇到的問題吧,答案以及解決辦法後面會給出。

  • 發佈到哪個Maven倉庫?
    Maven項目的信息及配置由pom.xml來存儲,其中包含了項目信息、開發者信息、依賴、插件等,如果想要獲取其他人或組織開發的jar包,那麼就要引入我們再熟悉不過的依賴了,依賴需要從倉庫下載,下載流程如下:
  1. 檢索本地倉庫,如果有該依賴返回成功,否則進入下一步;
  2. 檢索私有倉庫,如果有該依賴返回成功,否則進入下一步;
  3. 檢索中央倉庫,如果有該依賴返回成功,否則返回失敗。

本地倉庫是在每個開發者電腦上,一般在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

安裝好了之後你可以通過圖形界面生成祕鑰,也可以通過命令行生成,圖形界面操作簡單易懂就不演示了,下面演示命令行:

  1. 生成密鑰對:gpg --gen-key,此過程會讓你輸入用戶名密碼,用戶名隨便填即可,密碼請務必記住,因爲後面每次部署發佈的時候都會要輸入此密碼
  2. 查看公鑰id:gpg --list-keys,下一步需要用到;
  3. 將公鑰id發佈到GPG祕鑰服務器:gpg--keyserver hkp://keyserver.ubuntu.com:11371 --send-keys xxxxxxxxxxxxxxxxxxxx,假設我的公鑰id是xxxxxxxxxxxxxxxxxxxx;
  4. 檢查是否發送成功: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項目,也就是和筆者情況一樣,具體操作如下。

  1. 創建一個新的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>
  1. 將你的依賴安裝到本地倉庫:

    1. 如果你有一些class字節碼文件需要打成jar包,很簡單,隨便使用一個壓縮工具,把你的依賴項目工程壓縮成zip格式,注意一定是zip,因爲zip壓縮格式和jar格式是一樣的,打包之後直接把後綴名改成jar即可。

    2. 如果你只是一些jar包,沒有“散裝”的class字節碼文件,那麼就可以直接進入下一步操作。

    3. 用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
  2. 在pom中添加本地倉庫依賴

執行成功之後本地倉庫就有剛剛那個項目了,接下里把這個依賴添加到pom文件中,這裏的groupId、artifactId以及version和上面命令的內容一致。

<dependencies>
    <dependency>
        <groupId>com.github.tzfun</groupId>
        <artifactId>vmconsole-local</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>
  1. 配置發佈插件和倉庫地址。

一般只需要三個插件即可,但是這裏我多加了一個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之路關注

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章