# 发布自己的 jar 包到 Maven 中央仓库 ( mvnrepository.com )

# 注册 sonatype 的 Jira 帐号

SonaType 是什么呢?提供开源项目仓库托管 (Open Source Software Repository Hosting,简称 OSSRH) 服务。

注意:记录用户名和账号密码,后续发布 jar 文件时会使用到。

注册地址: https://issues.sonatype.org/secure/Signup!default.jspa

注册很简单,重要的是邮箱地址一定要正确,issue 有任何变动都会通过邮件通知。

# sonatype 网站设置中文语言

sonatype 的 Jira 帐号注册成功之后,登录进入首页界面如下:

image-20231010133923605

点击头像的个人信息设置:

image-20231010134155257

进入后点击这里就可以修改

image-20231010134456475

# 申请创建个人仓库工单

点击页面顶部的 创建 按钮,创建工单:

项目选择:Community Support - Open Source Project Repository Hosting (OSSRH)

问题类型选择:New Project

image-20231010134644384

填写表单信息:

表单中有如下信息需要填写:

  • Summary :描述自己包的作用
  • Description :可写可不写,也是具体描述的
  • Group Id :笔者有自己的域名,所以填写的是 cn.woodwhales.common,如果没有自己的域名,可以填写:github.xxx.yyy 或者 gitee.xxx.yyy。
  • Project URL :填写你的项目的 github 或者 gitee 地址
  • SCM url :填写你项目的 github 或者 gitee 的克隆地址

读者可以参考笔者的工单进行填写 https://issues.sonatype.org/browse/OSSRH-95650

image-20231010135027443

工单提交之后需要等待管理员审核。审核完成,管理员会在下面提示你让你验证这个域名是你的或者证明域名或者 gitee 或者 github 空间是你的。笔者没有用自己的域名所以没有域名解析配置,并且在 github 仓库中临时创建一个的名称为: OSSRH-73359 的公开仓库:

image-20231010135213502

创建 Github 仓库

image-20231010135331662

当上述步骤按照管理员要求验证之后,稍等片刻,就会收到管理员验证通过的信息:

image-20231010135358843

到此,我们可以按照管理员给的配置指南进行下一步操作了,可以不再使用 sonatype 网站。

值得注意是的是,工单的状态也变为 已解决 状态。

# 发布指南

参考管理员给的配置指南:https://central.sonatype.org/publish/publish-guide/#deployment,笔者是 maven 工程,所以点击 maven 工程配置指南:https://central.sonatype.org/publish/publish-guide/#deployment

image-20231010135554593

读者如果是其他版本控制工具,找到对应的文档自行配置即可,思路大致相同。

# 配置 maven 的 settings.xml

在自己本机的 maven 配置文件 settings.xml 中配置 <server>

copy<settings>
  <servers>
    <server>
      <id>ossrh</id>
      <username>sonatype 的 Jira 帐号</username>
      <password>sonatype 的 Jira 帐号的密码</password>
    </server>
  </servers>
</settings>

笔者建议这个 <id>ossrh</id> 不要修改,就使用官方指南的即可。

# GPG 签名配置

在等待 Issue 的时候可以先把密钥搞好

# 下载 GPG

sonatype 要求发布的 jar 需要使用 GPG 签名,所以需要安装 GPG,并生成密钥对。

GPG 下载地址:

  • windows 环境:https://www.gpg4win.org/download.html
  • mac 环境:https://gpgtools.org/

GPG 官网有各个环境的安装包下载地址:https://gnupg.org/download/index.html

image-20231010140419977

# 安装 GPG

安装 GPG 很简单,一直下一步即可安装成功。安装过程中要记得安装目录,后续会有使用到这个路径。

笔者安装在了 c 盘符下:

image-20231010140728734

值得注意的是 GPG 会自动注册到系统环境变量中,所以我们可以直接在 cmd 窗口中验证是否安装成功:

image-20231010140906285

展示出 GPG 版本信息表示安装成功。另外,安装成功之后,桌面会出现一个快捷图标:Kleopatra

# 生成 GPG 证书(密钥对)

可以使用 GPG 命令在 cmd 窗口生成,也可以打开 Kleopatra 桌面程序生成。

# 方式 1:命令生成

命令行生成生成秘钥: gpg --gen-key

按提示输入名字, 如:xxx,邮箱 xxx@163.com,然后选择 (O) kay,输入英文字母 o

弹出设置密码框,记住这个密码,稍后会使用到:

image-20231010141837686

image-20231010141853951

密码输入完成之后,程序生成密钥对,并展示出 GPG 公钥签名:

image-20231010142053566

查看本系统已生成的所有密钥对信息: gpg --list-keys

image-20231010142129523

# 方式 2:可视化生成

可视化的生成密钥对比命令行生成友好很多,并且直接展示已生成的所有密钥对信息:

image-20231010142546446

# 上传公钥证书至公钥服务器

使用 cmd 命令执行:

gpg --keyserver keyserver.ubuntu.com --send-keys 公钥签名

验证是否成功地上传到了两个服务器:

gpg --keyserver keyserver.ubuntu.com --recv-keys 公钥签名

image-20231010144219149

可能出现的上传失败问题

gpg: keyserver send failed: No name

image-20231010144401191

​ 解决办法

​ 替换上传的链接

gpg --keyserver keyserver.ubuntu.com --send-keys 【your public key】
gpg --keyserver keys.openpgp.org --send-keys 【your public key】
gpg --keyserver pgp.mit.edu --send-keys 【your public key】

​ 查询是否上传成功

gpg --keyserver keyserver.ubuntu.com --recv-keys 【your public key】
gpg --keyserver keys.openpgp.org  --recv-keys 【your public key】
gpg --keyserver pgp.mit.edu --recv-keys 【your public key】

​ 查询结果

image-20231010144635477

# 配置项目中的 pom.xml

在要发布的 maven 工程的 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>
    <groupId>cn.woodwhales.common</groupId>
    <artifactId>woodwhales-common</artifactId>
    <version>3.5.0</version>
    <name>woodwhales-common</name>
    <!-- 项目描述 -->
    <description>https://github.com/woodwhales</description>
    <url>https://github.com/woodwhales/woodwhales-common</url>
    <properties>
        <java.version>1.8</java.version>
        <!-- 文件拷贝时的编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <licenses>
        <!-- 开源协议 -->
        <license>
            <name>The Apache Software License, Version2.0</name>
            <url>http://www.apache.org/licenses/</url>
            <distribution>repo</distribution>
        </license>
    </licenses>
    <!-- scm -->
    <scm>
        <tag>master</tag>
        <url>https://github.com/woodwhales/woodwhales-common</url>
        <connection>scm:git:git://github.com:woodwhales/woodwhales-common.git</connection>
        <developerConnection>scm:git:git://github.com:woodwhales/woodwhales-common.git</developerConnection>
    </scm>
    
    <!-- issues -->
    <issueManagement>
        <system>GitHub Issue Management</system>
        <url>https://github.com/woodwhales/woodwhales-common/issues</url>
    </issueManagement>
    <!-- 开发者信息 -->
    <developers>
        <developer>
            <id>woodwhales</id>
            <name>woodwhales</name>
            <email>woodwhales@163.com</email>
            <url>https://woodwhales.cn/</url>
            <timezone>+8</timezone>
        </developer>
    </developers>
    <dependencies>
        ...
    </dependencies>
    <!-- distributionManagement -->
    <distributionManagement>
        <snapshotRepository>
            <id>ossrh</id>
            <url>https://s01.oss.sonatype.org/content/repositories/snapshots</url>
        </snapshotRepository>
        <repository>
            <id>ossrh</id>
            <url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
    </distributionManagement>
    <build>
        <plugins>
            <!-- maven 打包时附带源码文件插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <phase>verify</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>
                        <id>attach-javadocs</id>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <!-- sonatype staging 插件 -->
            <plugin>
                <groupId>org.sonatype.plugins</groupId>
                <artifactId>nexus-staging-maven-plugin</artifactId>
                <version>1.6.7</version>
                <extensions>true</extensions>
                <configuration>
                    <serverId>ossrh</serverId>
                    <nexusUrl>https://s01.oss.sonatype.org/</nexusUrl>
                    <autoReleaseAfterClose>true</autoReleaseAfterClose>
                </configuration>
            </plugin>
            <!-- maven-gpg 插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-gpg-plugin</artifactId>
                <version>1.5</version>
                <executions>
                    <execution>
                        <id>sign-artifacts</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>sign</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

对 maven 工程执行即可发布 jar 至 maven 仓库,注意工程版本不要带有 SNAPSHOT:

mvn clean deploy

发布成功之后,可以在 search.maven.org 中搜索到自己刚刚上传的 jar 文件。

并在 https://s01.oss.sonatype.org/#welcome 中使用 sonatype 的 Jira 账号登录,从 https://s01.oss.sonatype.org/content/groups/public/https://s01.oss.sonatype.org/content/repositories/releases/ 中可以看到发布的 jar 文件。

image-20231011105905850

image-20231011112609993

# 通知 Sonatype 构件已成功发布

通知 Sonatype 构件已成功发布,在之前创建的 Issue 中回复一条 The component has been successfully released 通知工作人员为需要发布的构件做审批,发布后会关闭该 Issue。

image-20231011113400688

看到整个同步过程需要 2 个小时左右,还是挺慢的……

# 检查同步是否成功

​ 除了通过 search.maven.org 检查同步是否成功之外,查询 mvnrepository 也是常用的搜索方式。不过,值得一提的是,mvnrepository 相较于 search.maven.org 同步会更慢点,原因是 mvnrepository 引用了 central.maven.org 仓库。而 central.maven.org == repo1.maven.org ,两个域名对应的 IP 是一样的,而这个 repo1.maven.org 就是默认的 Maven central repository,也就是 search.maven.org 的仓库。所以,你可以在以下两个仓库看到发布包:
http://central.maven.org/maven2/tech/sqlclub/
http://repo1.maven.org/maven2/tech/sqlclub/

据我实际测试发现,大概 release 之后不超过 20 分钟,就可以在
https://repo.maven.apache.org/maven2/ 这里查看到了,
只要这里有了,别人就可以依赖你提供的这个 jar 了。

# 以后发布过程

第一次提交才这么麻烦,以后提交只用重复 maven 发布,当然需要等待大概 2 小时的时间。
如果要发布新的项目,在使用相同 GroupId 的情况下,与上面的过程一样。只有使用不同的 GroupId 的时候,才会需要再去提交 Issue 申请。
当然如果你没有换电脑的话 GPG 的过程只需要一次就行。