最近在写一些开源项目,想把自己写的东西放到maven中央仓库,提供给更多的人使用。所以写这一篇文章,记录一下自研开源项目jar包上传同步maven中央仓库成功的整个过程,这其中还是有不少的坑的。

  • 一、OSSRH账号注册于配置
  • 1.1.账号注册
  • 1.2.域名认证
  • 二、安装GnuPG软件,并生成签名
  • 三、项目基础配置
  • 四、maven打包配置
  • 五、CLOSE&RELEASE

maven 从 中央仓库下载本地仓库 maven提交中央仓库_上传

  • 首先需要在sonatype JIRA管理平台完成新建项目的申请,审核通过之后才能进行上传jar的操作
  • 上传过程首先肯定是要本地进行打包,为保整项目信息完整性及上传过程安全性,需要进行特殊的操作,后文详述
  • 本地打包之后首先传入sonatype Nexus staging库,这个库只做临时存储,校验内容完整、信息完整之后才能通过平台操作转移到release库。
  • 开源项目jar转到到release库之后,实际上需要我们操作的内容就全都完成了。sonatype maven库的项目会自动同步到maven中央仓库,这个过程会有延时,但延时很短。
  • 如果你使用国内的maven中央仓库的镜像,与maven中央仓库会有比较大的延时,请耐心等待同步之后,才可以使用。

一、OSSRH账号注册于配置

sonatype是由社区支持的开源项目托管服务(Open Source Project Repository Hosting,简称OSSRH),它免费,开发者可以将自己的开源项目生成的maven jar包托管到这里。 「当将maven项目打包部署到这里之后,将自动同步到maven中央仓库。」 所以不管怎样,我们都需要先注册一个sonatype平台账号。

1.1.账号注册

注册地址:https://issues.sonatype.org/secure/Signup!default.jspa ,按照下图所示的内容填写自己的邮箱、全名、登陆用户名username、登陆密码passwprd,填写验证码即可完成注册。友情提示:注册过程中的密码的强度要求非常高,填写完成之后最好找个记事本把密码先记下来,以面后续使用的时候忘记。另外,注册完成之后,没有任何“注册成功”相关的提示,而是直接跳转到登录界面。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven 从 中央仓库下载本地仓库_02

使用我们刚刚注册的用户登陆进去,登陆进去之后会提示我们选择语言:我习惯中文,当然选中文;然后会提示我们选择一个头像;然后会提示我们要进行什么工作,“浏览当前项目即可”,这一步不重要。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_java_03

进入JIRA管理平台之后,点击顶部导航栏的“新建”按钮,然后在弹出的模态框中填写信息,如下:

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven_04

  • 项目和问题类型,一定要选对,按图操作
  • 概要内容填写项目名称即可,Group Id 根据项目的maven坐标按需填写,与maven项目pom配置一致。(这里需要注意:实际操作的时候,先把下文中的《1.2.域名认证》看完,再做这部操作,存在对应关系避免做错)
  • 代码上传GitHub之后的项目URL、scm版本管理url(带.git)依次如图填写。

点击新建即可,新建问题之后。实际上是发起了一个新建项目审核的审核工作流,会有人审核你所填写的信息。

1.2.域名认证

因为上文中Group ID我填写的是我自己购买的域名,所以我需要证明这个域名是我的。证明的方式也很简单,就是在我的域名购买的平台,给域名增加一条txt的域名解析记录,域名解析记录的值会在JIRA平台的流程审核结果记录中给出,如下图中的红色框起来的内容(本次新建项目申请的流水编号:OSSRH-83481)。

如果没有域名怎么办?没有域名你可以给Group Id填写github的用户域,如: com.github.<gihub用户名> 。填写github用户域,验证方式也不一样,需要你在github中新建一个空的仓库,仓库的名称是 OSSRH-83481  。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven_05

因为我的域名是在阿里云买的,所以我去阿里云为该域名添加一个TXT类型的解析记录值。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_开源_06

如果你不太确定TXT解析记录值是否生效,可以通过windows CMD命令行,响应如下的信息证明设置正确


> nslookup -type=TXT 你的域名
服务器:  dns.google
Address:  8.8.8.8

非权威应答:
你的域名       text =

        "OSSRH-83481"


域名解析记录值添加完成之后,回到sonatype JIRA管理平台。在 OSSRH-83481 问题里面如下图所示的位置,有一个Respose按钮,点击该按钮证明你已经完成了域名认证操作。(因为我是操作完成之后,写的这篇文章,所以这个按钮已经没了,我模拟了一个)

maven 从 中央仓库下载本地仓库 maven提交中央仓库_java_07

在整个的新建问题,项目流程审核过程中,你的注册邮箱会不断的收到sonatype JIRA管理平台发出的邮件,提示你审核流程进行到了什么阶段。(这个审核过程非常迅速,应该是机器人参与的审核,不是人为操作的,我用了5分钟就完成了整个审核流程). 审核通过之后,你会看到如下的状态:已解决。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven_08

二、安装GnuPG软件,并生成签名

新建项目审核通过之后,我们需要在开发PC上安装GnuPG,因为我们上传到sonatype maven库的所有文件都要经过GnuPG进行签名,不经过签名的文件无法上传成功。下载地址:https://gpg4win.org/thanks-for-download.html 。下载完成之后,傻瓜式的“下一步”“下一步”安装即可。下载完成之后,我们打开windows的 CMD命令行,执行如下命令。(注意:我的操作都是在CMD命令行下面执行的,不要power shell ,不要git bash。我都试过,不是不行,是操作过程不一致。如果和我的操作过程不一致,可能导致你操作失败!)


gpg --gen-key


下图中红色的部分是我填写的内容,我的名字、邮箱,以及一个O表示ok。会提示我们输入一个Passphrase,填写2遍。这个Passphrase就是一个密码,一定要记住,下文会用到。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_开源_09

GnuPG签名的公钥私钥对生成完成之后,可以使用如下命令查看结果


C:\Users\hanxt>gpg --list-key
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
gpg: next trustdb check due at 2024-08-09
C:\Users\hanxt\AppData\Roaming\gnupg\pubring.kbx
------------------------------------------------
pub   ed25519 2022-08-10 [SC] [expires: 2024-08-09]
      6B4F6A477A1BE195326AEAFA0EE41461FB92CD0B
uid           [ultimate] HanXiaotong <hanxiaotongtong@163.com>
sub   cv25519 2022-08-10 [E] [expires: 2024-08-09]


密钥对生成完成之后,将其公钥发往sonatype认可的keyserver,公钥的字符串可以通过上文中的 gpg --list-key 查看到


gpg --keyserver keyserver.ubuntu.com --send-keys 6B4F6A477A1BE195326AEAFA0EE41461FB92CD0B


通过下面的命令行,可以校验公钥的字符串发往服务器是否成功。


gpg --keyserver keyserver.ubuntu.com --recv-keys 6B4F6A477A1BE195326AEAFA0EE41461FB92CD0B


三、项目基础配置

完成上述的准备工作,我们要对项目进行打包了,打包工具我用的maven。需要检查如下信息是否配置完整,如果没有配置完整,请补充!缺少这些信息,maven项目后续将无法转成release状态。请根据自己项目的实际情况填写。


<groupId>com.zimug</groupId>
<artifactId>zimug-monitor-threadpool</artifactId>
<version>1.0</version>

<name>${project.groupId}:${project.artifactId}</name>
<description>spring boot starter  for thread pool monitor  </description>
<url>https://github.com/hanxt/zimug-monitor-threadpool</url>


license中填写开源协议,scm填写项目的git代码仓库地址,developer填写开发人员的联系方式。


<licenses>
    <license>
      <name>BSD 3-Clause</name>
      <url>https://spdx.org/licenses/BSD-3-Clause.html</url>
    </license>
  </licenses>
  <scm>
    <connection>https://github.com/hanxt/zimug-monitor-threadpool.git</connection>
    <url>https://github.com/hanxt/zimug-monitor-threadpool</url>
  </scm>
  <developers>
    <developer>
      <name>zimug</name>
      <email>hanxiaotongtong@163.com</email>
      <roles>
        <role>Developer</role>
      </roles>
      <timezone>+8</timezone>
    </developer>
  </developers>


四、maven打包配置

只有在sonatype JIRA管理平台上注册的用户,才能将开源项目 jar上传到sonatype Nexus 仓库。所以我们在上传jar文件的时候,有必要告知服务器端我们的注册用户名及密码。找到maven的setting.xml,添加如下配置:


<servers>
    <server>
      <id>ossrh</id> 
      <username>sonatype注册username</username>
      <password>sonatype注册用户的password</password>
    </server>
</servers>


setting.xml是针对maven进行全局配置,除此之外还需要针对项目进行配置pom.xml,首先配置远程仓库的地址。需要注意的是这里的id与setting.xml中sever配置的id要一致。


<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>


这里有几个需要注意的地方,

  • snapshotRepository是项目快照版本snapshot上传地址,如果项目的版本号,如:1.0-SNAPSHOT,会上传到这个仓库。
  • 通常情况下repository是我们真正需要发布项目的远程仓库上传地址。需要注意的是我们这里写的是staging暂存地址,而不是release版本的地址。(为什么这么做?后文详述)
  • 另外需要注意的是,我们上传的远程仓库的地址是带s01前缀的,而比较旧的文章中不带s01前缀。这是因为旧的sonatype maven仓库已经资源满载了,所以官方新建了一个s01 maven仓库,未来可能还会有s02、s03。现阶段在sonatype JIRA管理平台上注册的用户,只能上传这个新的s01仓库。

远程仓库配置完成之后,我们还需要针对项目pom.xml增加一些打包配置,这些配置基本不用修改,原样粘贴进去即可。(其中maven-gpg-plugin插件会调用上文中安装的GnuPG软件,对文件进行签名)


<profiles>
  <profile>
    <id>release</id>
    <build>
      <plugins>
        <!-- Source -->
        <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>
          <configuration>
            <show>private</show>
            <nohelp>true</nohelp>
            <charset>UTF-8</charset>
            <encoding>UTF-8</encoding>
            <docencoding>UTF-8</docencoding>
            <additionalparam>-Xdoclint:none</additionalparam>
            <!-- TODO 临时解决不规范的javadoc生成报错,后面要规范化后把这行去掉 -->
          </configuration>
          <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>
        <!--Compiler -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.0</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
            <fork>true</fork>
            <verbose>true</verbose>
            <encoding>UTF-8</encoding>
          </configuration>
        </plugin>
        <!--Release -->
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-release-plugin</artifactId>
          <version>2.5.1</version>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>


在项目根目录下,运行下面的命令进行maven打包操作(同时将项目jar deploy到远程maven仓库),在打包运行过程中,会弹出一个对话框提示你输入密钥(Passphrase),输入上文《安装GnuPG软件,并生成签名》章节中你填写的Passphrase即可。


mvn clean install deploy -P release

这里需要注意的是:

  • 不要使用IDEA的maven UI打包,IDEA的maven UI打包会报错,无法执行gpg命令。至于具体原因我也没搞清楚,使用上文中的CMD命令行打包即可。
  • 使用mvn命令行打包的时候,需要注意你的JAVA_HOME环境变量的指向,是不是你期望的版本。我的电脑上安装了多个版本的JDK,JAVA_HOME指向的是JDK11,而我希望打包的版本是JDK8。有可能造成混乱!
  • 如果maven depoly发布命令报401 authentication错误,是因为你的maven的setting.xml的server配置的用户名密码错误,或者setting.xml的server配置id与pom里面配置的repository id不一致导致的。也有可能你的电脑上maven 多个版本,项目使用的不是同一个setting.xml。
  • 如果报400错误,很有可能是你已经上传过的jar,同一个版本再次重复上传了。

五、CLOSE&RELEASE

项目jar正确的上传到nexus repository仓库之后,我们还需要进行进一步的操作。这是因为我们上传的jar放入了staging暂存库里面,我们需要把它转到release库,这其中sonatype平台会针对你的项目信息、jar文档、源码等内容进行完整性校验,完整性校验不通过的项目是无法转到release的,也就无法同步到maven中央仓库。

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven_10

这些操作需要我们通过界面进行,使用sonatype注册用户进行登录:https://s01.oss.sonatype.org/ 。如图所示,如果我们项目打包上传成功,会在Staging Repository里面看到一个Repository,将其勾选。点击“CLOSE”按钮之后,会自动进行完整性校验,校验结果可以双击勾选仓库所在行进行查看。(只要按照我上文中的内容,将pom中的项目信息以及打包配置填写完整,这里基本都会校验通过)

maven 从 中央仓库下载本地仓库 maven提交中央仓库_maven_11

CLOSE校验通过之后,刷新几次页面,Release按钮就变成可点击的状态。此时点击Release按钮,就将项目jar从Staging暂存库,转移到了Release正式库。实际上需要我们操作的内容就全都完成了。

sonatype maven库的项目会自动同步到maven中央仓库,通过maven坐标引入使用即可,不要着急,这个过程可能会有一些延时。上传之后可能一段时间内无法在maven中央仓库搜索到,但是使用maven坐标下载jar包也没有问题。

一切都ok之后,最好回到sonatype JIRA管理平台将“问题”关闭,这样sonatype JIRA管理流程就全部完成了。