圖文教程:從0到1將專案釋出到 Maven 中央倉庫

不止编码發表於2024-09-01

前言

本文基於官方文件 https://central.sonatype.org/publish/publish-guide/ 編寫。

釋出步驟:

  1. 建立賬號
  2. 建立使用者 Token
  3. 建立名稱空間
  4. 配置 GPG
  5. 配置專案
  6. 釋出

注意事項:

  • 釋出成功的專案無法修改或者刪除

準備階段

建立賬號

已有 Google 或者 Github 賬號可以跳過此步驟,可以直接使用它們關聯登入。

建立賬號步驟如下:

  1. 開啟官網 https://central.sonatype.com/ 點選右上角的Sign In,然後在開啟的登入頁中點選Sign up
    注意:郵箱要填寫真實的郵箱,有驗證的。
    官網
    登入頁

  2. 註冊成功之後會提示驗證郵箱。
    郵箱驗證提示

  3. 開啟郵箱,收取郵件,點選Confirm My Account驗證郵箱。
    郵件

  4. 在開啟的頁面中提示郵箱已驗證,表示註冊成功。
    郵箱驗證成功

建立使用者 Token

  1. 開啟官網 https://central.sonatype.com/ 點選右上角的Sign In,然後在開啟的登入頁直接輸入使用者名稱和密碼登入,也可以直接選擇 Google 或者 Github 關聯登入。

  2. 點選右上角的賬號,在下拉選單中選擇View Account
    View Account

  3. 點選Generate User Token
    Generate User Token

  4. 然後在彈出來的對話方塊中點選Ok,就會生成如下形式的 Token。

    <server>
       <id>${server}</id>
       <username>0j6XV+5V</username>
       <password>lSbp/2aMFiSiyzwNstB9zmzo6+5YyLqNHr9JDD8yKC5T</password>
    </server>
    

    注意這裡的id資訊,需要改成你自定義的,後面會用到。然後將上述內容複製到要釋出專案使用的settings.xml檔案中,這裡將id值改為central

    <servers>
       <server>
          <id>central</id>
          <username>0j6XV+5V</username>
          <password>lSbp/2aMFiSiyzwNstB9zmzo6+5YyLqNHr9JDD8yKC5T</password>
       </server>
    </servers>
    

建立名稱空間

官網對名稱空間的解釋:

Before you can publish your components, you must choose a namespace. In the Maven ecosystem, this is also known as a groupId, which is one of the three required coordinates to describe any component published to Maven Central, i.e. groupId, artifactId, version.

在釋出元件之前,你必須選擇一個名稱空間。在Maven生態系統中,這也被稱為groupId,它是描述釋出到Maven Central的任何元件所需的三個座標之一,即groupId、artifactId、version。

有兩種方式選擇你的名稱空間:

  1. 你擁有域名,可以使用反向域名的方式來作為名稱空間,如下所示:

    • www.springframework.org -> org.springframework
    • subdomain.example.com -> com.example
    • my-domain.com -> com.my-domain

    這種方式需要為對應的域名新增指定的域名解析以驗證你對域名的所有權,驗證成功之後可刪除。

  2. 你擁有以下列表中的程式碼託管服務賬號,可以使用個人域名的反向域名的方式來作為名稱空間

    Service Example namespace
    GitHub io.github.myusername
    GitLab io.gitlab.myusername
    Gitee io.gitee.myusername
    Bitbucket io.bitbucket.myusername

    這種方式需要在對應的賬號下建立指定名稱的公共倉庫以驗證賬號所有權,驗證成功之後可刪除。

建立名稱空間步驟如下:

  1. 開啟官網 https://central.sonatype.com/ 點選右上角的Sign In,然後在開啟的登入頁直接輸入使用者名稱和密碼登入,也可以直接選擇 Google 或者 Github 關聯登入。

  2. 點選右上角的賬號,在下拉選單中選擇View Namespaces
    View Namespaces

  3. 在開啟的頁面中點選Add Namespace
    Add Namespace

  4. 在彈出來的對話方塊中輸入自定義的 Namespace。
    Namespace

  5. 建立成功之後顯示 Namespace 是待驗證狀態,點選Verify Namespace進行驗證。
    Verify Namespace

  6. 在彈出來的對話方塊中會根據你填寫的 Namespace 型別不同,給出不同的提示,如果你填寫的是程式碼託管服務的個人域名,會提示你到對應的平臺中建立一個指定名稱的公共倉庫;如果是個人域名,會提示你建立一個指定內容的TXT型別的域名解析。總之你會得到一個Verification Key,你需要使用這個值去做對應的操作。點選對話方塊的Confirm按鈕,Namespace 變成待驗證狀態:
    待驗證
    以下兩種驗證方式,選擇一種即可:

    • 建立公共倉庫:
      建立公共程式碼倉庫
    • 增加域名解析:
      新增域名解析
  7. 等待 Namespace 驗證成功,然後可以把剛剛建立的公共倉庫或新增的域名解析記錄刪除。
    Namespace驗證成功

配置 GPG

  1. 開啟官網https://gnupg.org/download/index.html#sec-1-2下載系統對應的版本並安裝。使用gpg --version驗證是否安裝成功。

    C:\Users\Administrator>gpg --version
    gpg (GnuPG) 2.3.8
    libgcrypt 1.10.1
    Copyright (C) 2021 g10 Code GmbH
    License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Home: C:\Users\Administrator\AppData\Roaming\gnupg
    Supported algorithms:
    Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
    Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
          CAMELLIA128, CAMELLIA192, CAMELLIA256
    AEAD: EAX, OCB
    Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
    Compression: Uncompressed, ZIP, ZLIB, BZIP2
    
  2. 使用gpg --gen-key命令生成金鑰對,過程中會提示輸入Real nameEmail address(建議輸入真實的郵箱,以便以後用於秘鑰恢復),輸入之後,會彈窗要求你輸入密碼(注意:每次釋出專案都會用到這個密碼),然後就會生成金鑰對。
    下面內容中的5BBA74D9F7E76AAA234ACB337B583099E6B290D8就是生成的公鑰,接下來需要把它傳送到秘鑰伺服器,因為其他人需要這個公鑰來驗證你釋出的檔案。

    C:\Users\Administrator>gpg --gen-key
    gpg (GnuPG) 2.3.8; Copyright (C) 2021 g10 Code GmbH
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Note: Use "gpg --full-generate-key" for a full featured key generation dialog.
    
    GnuPG needs to construct a user ID to identify your key.
    
    Real name: t1
    Email address: t1@test.com
    You selected this USER-ID:
       "t1 <t1@test.com>"
    
    Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    gpg: revocation certificate stored as 'C:\\Users\\Administrator\\AppData\\Roaming\\gnupg\\openpgp-revocs.d\\5BBA74D9F7E76AAA234ACB337B583099E6B290D8.rev'
    public and secret key created and signed.
    
    pub   ed25519 2024-08-26 [SC] [expires: 2026-08-26]
          5BBA74D9F7E76AAA234ACB337B583099E6B290D8
    uid                      t1 <t1@test.com>
    sub   cv25519 2024-08-26 [E] [expires: 2026-08-26]
    
  3. 使用gpg --keyserver keyserver.ubuntu.com --send-keys <公鑰>命令將公鑰傳送至伺服器,如果出現傳送失敗的情況,可以選擇其他伺服器多次重試,總會成功的。

    中央伺服器支援的GPG金鑰伺服器有:

    • keyserver.ubuntu.com
    • keys.openpgp.org
    • pgp.mit.edu
    # 傳送公鑰
    C:\Users\Administrator>gpg --keyserver keyserver.ubuntu.com --send-keys 5BBA74D9F7E76AAA234ACB337B583099E6B290D8
    gpg: sending key 7B583099E6B290D8 to hkp://keyserver.ubuntu.com
    
    # 驗證公鑰失敗
    C:\Users\Administrator>gpg --keyserver keyserver.ubuntu.com --recv-keys 5BBA74D9F7E76AAA234ACB337B583099E6B290D8
    gpg: keyserver receive failed: No data
    
    # 驗證公鑰成功
    C:\Users\Administrator>gpg --keyserver keyserver.ubuntu.com --recv-keys 5BBA74D9F7E76AAA234ACB337B583099E6B290D8
    gpg: key 7B583099E6B290D8: "t1 <t1@test.com>" not changed
    gpg: Total number processed: 1
    gpg:              unchanged: 1
    

配置專案

以下為一個專案完整的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>

    <groupId>cc.minghe</groupId>
    <artifactId>no-bug-spring-boot-starter</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <name>No Bug</name>
    <description>Bug退散,Buff拉滿</description>
    <url>https://github.com/iminghe/no-bug</url>

    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <scm>
        <url>https://github.com/iminghe/no-bug</url>
        <connection>scm:git:https://github.com/iminghe/no-bug.git</connection>
        <developerConnection>scm:git:https://github.com/iminghe/no-bug.git</developerConnection>
    </scm>

    <developers>
        <developer>
            <name>minghe</name>
            <email>iminghe@xxx.com</email>
        </developer>
    </developers>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.7.18</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <!-- Source -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.3.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- Javadoc -->
            <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-javadoc-plugin</artifactId>
               <version>3.10.0</version>
               <executions>
                     <execution>
                        <id>attach-javadocs</id>
                        <goals>
                           <goal>jar</goal>
                        </goals>
                     </execution>
               </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>release</id>
            <build>
                <plugins>
                    <!-- GPG -->
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-gpg-plugin</artifactId>
                        <version>3.2.5</version>
                        <executions>
                            <execution>
                                <id>sign-artifacts</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>sign</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.sonatype.central</groupId>
                        <artifactId>central-publishing-maven-plugin</artifactId>
                        <version>0.5.0</version>
                        <extensions>true</extensions>
                        <configuration>
                            <publishingServerId>central</publishingServerId>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

說明:

  • groupId:前面步驟認證的 Namespace。
  • licenses:專案的許可證資訊。
  • scmsource control system,原始碼管理系統。這部分元素是必需的,如果URL本身不需要是公開的。你可以指定一個公眾無法訪問的URL,甚至是一個佔位符,指出你的SCM URL是私有的,不適合公眾訪問。
  • developers:開發人員資訊。
  • build:打包的公共外掛。
  • profiles:定義不同環境的配置,使用id作為標識,可用於執行mvn命令時,選擇指定環境。這裡定義了release環境用於專案釋出,其中central-publishing-maven-plugin是用來發布專案的,其中publishingServerId對應使用者Token設定的id

釋出階段

Profiles選中release,然後依次執行cleandeploy命令。
釋出

或者也可以在終端的本專案目錄下直接執行mvn clean deploy -P release

等待命令執行完成,然後登入官網,點選右上角的賬號,選擇View Deployments,會看到已驗證待發布的專案。
釋出頁面

確認無誤後,點選Publish,狀態會變為PUBLISHING,然後等待一會兒,狀態變為PUBLISHED,就代表釋出成功了,恭喜你!

相關文章