2026 最新:从 0 开始将 Java 项目发布到 Maven Central

前言

本文记录 2026 年使用 Sonatype Central Publisher Portal 发布 Java/Maven 项目的完整流程。

本文已经不再使用旧版的 issues.sonatype.orgs01.oss.sonatype.org、Staging Repository、Close/Release 等旧流程,而是使用目前 Sonatype 官方推荐的 Central Publisher Portal + central-publishing-maven-plugin 方案。

本文以 Windows + JDK 21 + Maven + GnuPG/Kleopatra 为例。


发布 Maven Central 的完整流程

现在发布一个 Java 项目到 Maven Central,大致分成下面几个步骤:

text 复制代码
1. 注册 Sonatype Central Portal
        ↓
2. 创建并验证 Namespace
        ↓
3. 安装 GnuPG / Kleopatra
        ↓
4. 创建 GPG 密钥
        ↓
5. 将 GPG 公钥发布到公共 Key Server
        ↓
6. Maven POM 配置
        ↓
7. 配置 Central User Token
        ↓
8. mvn clean deploy
        ↓
9. Central Portal 自动验证
        ↓
10. Publish
        ↓
11. Maven Central 同步完成

Sonatype 当前的 Maven 发布方式使用 central-publishing-maven-plugin,执行 mvn deploy 后会生成 bundle 并上传到 Central Publisher Portal,然后进行验证。


准备工作

1.环境

本文案例使用:

text 复制代码
JDK 21
Maven 3.9+

2.一个公开的代码仓库

项目最好拥有公开的 GitHub、Gitee、GitLab 等代码仓库。

例如:

text 复制代码
项目:
yhchat-sdk-core

代码仓库:
Gitee / GitHub

Central 对 Namespace 有明确的归属验证要求。

如果使用 Gitee、GitHub 等代码托管平台,也可以按照 Central 当前支持的规则申请对应 Namespace。


一、注册 Sonatype Central Portal

访问:Sonatype Central Portal

登录或者注册账号,账号和Gitee或者Github的账号保持一致。

注意:

以前很多教程会让你访问 issues.sonatype.org 创建 JIRA 工单。

2026 年新项目不需要再按照这种旧教程操作。

当前应该使用 Central Publisher Portal 管理 Namespace 和发布。


二、创建并验证 Namespace

1.创建

登录 Central Portal 后,进入自己的 Namespace 管理页面。

通常可以从右上角账号菜单进入:View Namespaces

然后点击:Register New Namespace

Central 中的 Namespace 可以理解成 Maven 中的顶级 groupId

例如:cn.daenx

那么以后你的 Maven 项目可以使用:

xml 复制代码
<groupId>cn.daenx</groupId>

Central 要求你证明自己拥有这个 Namespace。

目前主要有两种方式:

  1. DNS 域名验证
  2. GitHub/Gitee/GitLab/Bitbucket 等代码托管平台对应的 Namespace 验证

Central 官方目前支持类似:

text 复制代码
GitHub:
io.github.你的用户名

Gitee:
io.gitee.你的用户名

GitLab:
io.gitlab.你的用户名

Bitbucket:
io.bitbucket.你的用户名

具体以 Central Portal 当前页面提供的选项为准。

2.使用自己的域名验证 Namespace

如果你拥有域名:example.com,那么可以使用:com.example作为 Namespace。

例如我拥有:daenx.cn,那么可以申请:cn.daenx

申请之后,Central 会生成一个:Verification Key

然后需要去域名 DNS 管理后台增加 TXT 记录。

例如:

text 复制代码
类型:TXT

主机记录:
根据 Central 页面提供的信息填写

记录值:
Central 生成的 Verification Key

DNS 生效后回到 Central Portal 点击:Verify Namespace

等待状态变成:Verified即可。


三、获取User Token

Central Publisher Portal 使用 User Token 进行 Maven 发布。

进入:Central User Token 页面

注意:

Token 页面关闭之后,Token 凭证不会再次完整显示,所以生成后一定保存好。

官方文档也明确说明 Token 关闭弹窗后不能重新取回。


四、配置Maven settings.xml

找到 Maven:settings.xml

增加:

xml 复制代码
<settings>
    <servers>
        <server>
            <id>central</id>
            <username>生成的User Token Username</username>
            <password>生成的User Token Password</password>
        </server>
    </servers>
</settings>

注意这里:

xml 复制代码
<id>central</id>

必须和下文的 POM 中:

xml 复制代码
<publishingServerId>central</publishingServerId>

对应。


五、安装 GnuPG / Kleopatra

Maven Central 要求发布的文件使用 GPG/PGP 签名。

官方要求每一个部署文件都应该有对应的 .asc 签名文件。

Windows 推荐使用:Gpg4win 官方网站


六、使用 Kleopatra 创建 GPG 密钥

打开 Kleopatra。

选择:文件新建 OpenPGP 密钥对

填写:

text 复制代码
姓名:你的名字(建议和Gitee或者Github的账号保持一致)

邮箱:你的邮箱(建议和Gitee或者Github的邮箱保持一致)

例如:

text 复制代码
姓名:
DaenMax

邮箱:
1330166565@qq.com

有效期设置长一点

建议给密钥设置一个密码,这个密码是以后 Maven 使用 GPG 签名时需要使用的密码。

⚠️ 这个密码一定要记住。 如果忘记密码,无法恢复。


七、配置 Kleopatra 发布服务器并发布 GPG 公钥

1.配置

这是 Maven Central 发布过程中非常重要的一步。

Central 官方目前支持以下公共 GPG Key Server:

text 复制代码
keyserver.ubuntu.com
keys.openpgp.org
pgp.mit.edu

官方文档明确要求将自己的公钥分发到 Key Server,Central 才能通过公钥验证你的签名。

我个人建议使用:

text 复制代码
keyserver.ubuntu.com

打开软件,设置配置 KleopatraGnuPG 系统Network

找到:use keyserver at URL

这里填写:hkps://keyserver.ubuntu.com

2.发布

回到证书列表,右键自己的证书:

text 复制代码
在服务器上发布

或者类似:

text 复制代码
Export to Keyserver

具体菜单名称可能根据 Kleopatra 版本略有不同。

如果成功,就代表公钥已经发布。


八、配置项目POM

1.基本信息

下面开始配置 Maven 项目。

假设:

text 复制代码
groupId:
cn.daenx

artifactId:
yhchat-sdk-core

version:
1.3.0

那么最终 Maven 坐标就是:

text 复制代码
cn.daenx:yhchat-sdk-core:1.3.0

POM 必须包含的基本信息

Central 对 Maven POM 有一些强制要求,包括:

  • groupId
  • artifactId
  • version
  • name
  • description
  • url
  • licenses
  • developers
  • scm

官方要求可以参考 Central 的 Requirements 文档。

基本结构:

xml 复制代码
<groupId>cn.daenx</groupId>
<artifactId>yhchat-sdk-core</artifactId>
<version>1.3.0</version>

<name>yhchat-sdk-core</name>

<description>
    yhchat-sdk-core 是一个 Java SDK。
</description>

<url>https://gitee.com/daenmax/yhchat-sdk-core</url>

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

<developers>
    <developer>
        <id>DaenMax</id>
        <name>DaenMax</name>
        <email>1330166565@qq.com</email>
    </developer>
</developers>

<scm>
        <connection>scm:git:https://gitee.com/daenmax/yhchat-sdk-core.git</connection>
        <developerConnection>scm:git:ssh://git@gitee.com/daenmax/yhchat-sdk-core.git</developerConnection>
        <url>https://gitee.com/daenmax/yhchat-sdk-core</url>
</scm>

2.配置生成 Sources.jar插件

xml 复制代码
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-source-plugin</artifactId>
    <version>3.3.1</version>
    <executions>
        <execution>
            <id>attach-sources</id>
            <phase>package</phase>
            <goals>
                <goal>jar-no-fork</goal>
            </goals>
        </execution>
    </executions>
</plugin>

3.配置生成 Javadoc.jar插件

xml 复制代码
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <version>3.11.2</version>
                <configuration>
                    <doclint>none</doclint>
                    <charset>UTF-8</charset>
                    <docencoding>UTF-8</docencoding>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <phase>package</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

4.配置 GPG 签名插件

xml 复制代码
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-gpg-plugin</artifactId>
    <version>3.2.8</version>
    <executions>
        <execution>
            <id>sign-artifacts</id>
            <phase>verify</phase>
            <goals>
                <goal>sign</goal>
            </goals>
        </execution>
    </executions>
</plugin>

5.配置 Central Publishing Plugin发布插件

xml 复制代码
            <plugin>
                <groupId>org.sonatype.central</groupId>
                <artifactId>central-publishing-maven-plugin</artifactId>
                <version>0.11.0</version>
                <extensions>true</extensions>
                <configuration>
                    <publishingServerId>central</publishingServerId>
                    <autoPublish>false</autoPublish>
                    <waitUntil>validated</waitUntil>
                    <checksums>all</checksums>
                </configuration>
            </plugin>

6.完整 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.16</version>
        <relativePath/>
    </parent>
    <groupId>cn.daenx</groupId>
    <artifactId>yhchat-sdk-core</artifactId>
    <version>1.3.0</version>
    <packaging>jar</packaging>
    <name>yhchat-sdk-core</name>
    <description>
        yhchat-sdk-core是云湖社交的Java版本的SDK核心服务,通过此Core可以快速构建您的云湖机器人,能让您以非常便捷的方式和云湖服务进行交互。
    </description>
    <url>https://gitee.com/daenmax/yhchat-sdk-core</url>
    <properties>
        <java.version>21</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <hutool.version>5.8.47</hutool.version>
    </properties>
    <dependencies>
        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- Hutool -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
            <optional>true</optional>
        </dependency>
        <!-- Apache Commons -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    
    
    <!-- License -->
    <licenses>
        <license>
            <name>Apache License, Version 2.0</name>
            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
        </license>
    </licenses>
    <!-- Developer -->
    <developers>
        <developer>
            <id>DaenMax</id>
            <name>DaenMax</name>
            <email>1330166565@qq.com</email>
            <roles>
                <role>Developer</role>
            </roles>
            <timezone>+8</timezone>
        </developer>
    </developers>
    <!-- SCM -->
    <scm>
        <connection>scm:git:https://gitee.com/daenmax/yhchat-sdk-core.git</connection>
        <developerConnection>scm:git:ssh://git@gitee.com/daenmax/yhchat-sdk-core.git</developerConnection>
        <url>https://gitee.com/daenmax/yhchat-sdk-core</url>
    </scm>

    <!-- Build -->
    <build>
        <plugins>
            <!-- Compiler -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <release>${java.version}</release>
                </configuration>
            </plugin>
            <!-- Source JAR -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.3.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <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>3.11.2</version>
                <configuration>
                    <doclint>none</doclint>
                    <charset>UTF-8</charset>
                    <docencoding>UTF-8</docencoding>
                    <encoding>UTF-8</encoding>
                </configuration>
                <executions>
                    <execution>
                        <id>attach-javadocs</id>
                        <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>3.2.8</version>
                <executions>
                    <execution>
                        <id>sign-artifacts</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>sign</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- Maven Central -->
            <plugin>
                <groupId>org.sonatype.central</groupId>
                <artifactId>central-publishing-maven-plugin</artifactId>
                <version>0.11.0</version>
                <extensions>true</extensions>
                <configuration>
                    <publishingServerId>central</publishingServerId>
                    <autoPublish>false</autoPublish>
                    <waitUntil>validated</waitUntil>
                    <checksums>all</checksums>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

九、执行 Maven Central 发布

打开项目,cmd

bash 复制代码
mvn clean deploy

新的 Central Publishing Plugin 会接管 deploy 流程,将项目构建结果生成 bundle 并上传到 Central Publisher Portal。


十、进入 Sonatype Central Portal 查看并发布

登录:Sonatype Central Portal

进入Deployments,点击Publish

发布成功后,组件会同步到 Maven Central。


十一、发布完成

发布成功后,就可以在 Maven Central 搜索你的组件。

例如:

text 复制代码
cn.daenx:yhchat-sdk-core:1.3.0

也可以直接在项目中使用:

xml 复制代码
<dependency>
    <groupId>cn.daenx</groupId>
    <artifactId>yhchat-sdk-core</artifactId>
    <version>1.3.0</version>
</dependency>

至此,就完事了,在 Maven Central 可以立即搜索到

Maven Repository大概第二天才能搜索到

(在此期间,无法搜索到也不影响项目中使用坐标引用你的项目)


其他命令参考

复制代码
# 使用CMD执行

# 安装到本地仓库
mvn clean install -Dgpg.skip=true

# 打包并上传到maven仓库
mvn clean deploy

本文最后更新时间:2026-08-16