2022年1月最新实践将依赖上传Maven中央仓库

上传中央仓库

需求分析

在使用某个官方网站的第三方依赖时,发现Maven中央仓库中没有,引入失败,又不想用lib方式来导入依赖,于是尝试将依赖上传中央仓库

前言

2022/01/26实践并撰写

受到Maven中央仓库上传地址以及首次上传的规则都有更新(2021年官方换了新版),因此要以最新的配置操作为准

上传流程

  • 注册sonatype账号
  • 创建ISSUE工单并提交
  • 官方审核并发邮箱提示提供本人确认
  • 提供本人证明并回复官方确认让官方再次审核
  • 官方审核通过工单创建完成,sonatype仓库激活
  • 按要求将源码分别上传snapshot版和release版
  • 官方发邮箱通知二者上传成功,同步至中央仓库自动被触发
  • 等待同步完成,结束

Maven依赖上传中央仓库流程

注册sonatype

  • sonatype官网注册一个sonatype账号,密码要求较高,大小写英文数字符号,都要,而且位数也有要求,记不住要保存好

  • 注册好后,官方会发邮箱通知,如果忘记也可以找回

    sonatype注册成功通知

  • 用户界面里完善个人信息,注意语言尽量使用英文,别用中文,开发者的好习惯

创建工单

直接点击网站上的Create按钮即可,进入表单模态框

创建ISSUE工单 1

创建ISSUE工单 2

  • Project 项目类型:默认是Community Support - Open Source Project Repository Hosting (OSSRH),这边不用改
  • Issue Type 工单类型:默认是New Project,这边不用改
  • Summary 项目主题:根据自己需要上传的依赖取一个名字,这个名字会用于在搜索这个依赖的时候进行搜索
  • Description 项目描述:根据自己需要上传的依赖写一个描述,这个描述会用于搜索到这个依赖后进行显示

创建ISSUE工单 3

  • Attachment 附件:根据需要加附件,这边没有加

  • Group Id 组号标识:Maven依赖引用时的标识

    • 如果有域名可以写正式域名

    • 如果没有域名,就写git的平台域名作为组号标识,比如使用github的域名

      注意:个人的名义必须是io开头,如果写com开头的话,申请会被驳回

  • Project URL 项目地址:对应自己的项目开源地址,这边用了github

  • SCM url 源码地址:对应项目的源码地址,如果是git的话,就在项目地址后加.git

  • Username(s) 用户名:填写sonatype账号的用户名,

    注意:这边不是邮箱,是用户名

  • Already Synced to Central是否已经推送到中央仓库:一般创建时都是没推的,所以选No

  • Create 创建:确认无误后,点击创建工单Create

工单审核

创建成功后,邮箱会首先收到一份工单创建的通知

ISSUE工单创建成功通知

接下来就是等待官方对工单的审核,是否合法,如果没问题,会进行后续的成功邮箱回复,如果没成功也别着急,按照官方给出的修改方法进行修改就行;

由于中国美国两地有时差,美国比中国慢13个小时,所以这步有一定的时间需要等待

如果运气好,官方马上就给回复了

官方提供本人证明通知

官方发邮箱提示需要进行两个步骤

  • 按照工单号创建一个github仓库用于验证是不是本人提交的工单
  • 修改工单号的状态为开放Open状态

本人证明

github仓库只要简单的创建就行了,这边不多细说,但是需要注意这个仓库必须是PUBLIC公开的,不然官方无法看到有这么个仓库

提供本人证明

切换状态

修改工单状态需要在sonatype网站左侧的导航栏处选择到自己的工单,选择Reported by me即可

查看工单状态

由于此时总结撰写时,这个工单已经解决结束了,所以是RESOLVED的状态

举一个其他的工单的状态例子,正常的话此时应该是WATING FOR RESPONSE状态,旁边有一个按钮RESPONSE供发起者点击,点击后就是回复官方我已经做好了本人证明的操作了,即创建了一个工单号的GitHub仓库

切换工单状态

RESPONSE后,转换到OPEN状态后,官方会自动回一封切换状态成功的邮件

切换工单状态开放成功通知

官方审核

此处可能又是一个漫长的等待的过程,如果官方审核发现本人证明无误后,会发送两封邮箱,一封是由于成功激活仓库,邀请填写意见反馈表

官方审核本人证明通过通知1

意见反馈表可选填写,看心情~

第二封比较重要,官方验证此域名/账户确实是本人的之后,会再次发送邮件,告知仓库已经被激活了,此时需要按照他们的要求,分别上传项目的SNAPSHOT和 RELEASE版本至指定地址

官方审核本人证明通过通知2

其中有提供官方帮助文档,如果步骤走不下去,请务必查阅官方文档,以官方文档为准,因为可能会有更新

获取源码

  • 在上传之前,先确定有这个依赖的源码,可以从提供依赖的官方下载;

  • 当然如果已经有打包好的jar包依赖了,可以直接尝试发布,后面就不用再打包了;

  • 另外如果需要由jar包获取源码,则需要使用一些Java的反编译工具

开源项目

  • 此处的项目是指创建Maven项目,将源码文件放加入项目中即可,后续将用Maven指令打包和进行发布;
  • 简单测试一下源码能不能用,确保可以用
  • 源码上传到对应的Git平台进行开源

配置密钥

用于包发布的时候,进行加密传输,这步是必须的

  • 安装GPG

    GNUPG官网下载并安装GPG

    根据自己的系统选择下载对应的版本

    如果是windows系统,则选择Gpg4win下载

    安装的时候一路默认即可,可以自定义安装到对应的盘,

    比如安装到D盘D:\Gpg4win,安装后,会发现与其同目录下还有一个GnuPG

  • 配置GPG环境变量

    它的环境变量是默认这样配置的D:\Gpg4win\..\GnuPG\bin

    所以最终的环境变量应该是GunPG下的bin目录,如果环境变量没配置好,可以手动配置

  • 命令行配置密钥

    生成秘钥有两种方式,命令行配置和UI界面配置两种,命令行更方便

    配置环境变量主要目的是可以链接访问GunPG下的bin目录下的可执行文件,进行命令行输入,如果没配置也可以键入这个目录直接输入命令

    • 生成密钥对

      gpg --gen-key

      C:\Users\slipperySoap>gpg --gen-key
      gpg (GnuPG) 2.3.4; 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.
      
      gpg: keybox 'C:\\Users\\slipperySoap\\AppData\\Roaming\\gnupg\\pubring.kbx' created
      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: slipperySoap
      Email address: slipperysoap@qq.com
      You selected this USER-ID:
          "slipperySoap <slipperysoap@qq.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: C:\\Users\\slipperySoap\\AppData\\Roaming\\gnupg\\trustdb.gpg: trustdb created
      gpg: directory 'C:\\Users\\slipperySoap\\AppData\\Roaming\\gnupg\\openpgp-revocs.d' created
      gpg: revocation certificate stored as 'C:\\Users\\slipperySoap\\AppData\\Roaming\\gnupg\\openpgp-revocs.d\\9CCCFA474A6D0987DF4239A305C07CEA48D53ECA.rev'
      public and secret key created and signed.
      
      pub   ed25519 2022-01-26 [SC] [expires: 2024-01-26]
            9CCCFA474A6D0987DF4239A305C07CEA48D53ECA
      uid                      slipperySoap <slipperysoap@qq.com>
      sub   cv25519 2022-01-26 [E] [expires: 2024-01-26]
      

      生成后一大段信息,其中要求输入的是以下信息

      Real name: 英文真实名(方便起见取了sonatype的用户名slipperySoap)
      Email address: 邮箱(方便起见也用了sonatype的邮箱slipperysoap@qq.com)
      You selected this USER-ID:
          "slipperySoap <slipperysoap@qq.com>"
      
      Change (N)ame, (E)mail, or (O)kay/(Q)uit? o
      

      输入o回车之后会要求设置Passphase,输入两次即可,务必牢记

    • 查询公钥

      gpg --list-keys

      C:\Users\slipperySoap>gpg --list-keys
      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-01-26
      C:\Users\slipperySoap\AppData\Roaming\gnupg\pubring.kbx
      -------------------------------------------------------
      pub   ed25519 2022-01-26 [SC] [expires: 2024-01-26]
            9CCCFA474A6D0987DF4239A305C07CEA48D53ECA
      uid           [ultimate] slipperySoap <slipperysoap@qq.com>
      sub   cv25519 2022-01-26 [E] [expires: 2024-01-26]
      

      其中pub中的第二行就是公钥标识,此处是9CCCFA474A6D0987DF4239A305C07CEA48D53ECA

    • 发布公钥

      gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 公钥标识

      C:\Users\slipperySoap>gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 9CCCFA474A6D0987DF4239A305C07CEA48D53ECA
      gpg: sending key 05C07CEA48D53ECA to hkp://keyserver.ubuntu.com:11371
      
    • 查询公钥发布

      gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys 公钥标识

      C:\Users\slipperySoap>gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys 9CCCFA474A6D0987DF4239A305C07CEA48D53ECA
      gpg: key 05C07CEA48D53ECA: "slipperySoap <slipperysoap@qq.com>" not changed
      gpg: Total number processed: 1
      gpg:              unchanged: 1
      

      如果成功,则是如上返回

打包配置

打包配置分开配置,因为部分涉及密码,pom中的信息是公开的,不可能把密码都公开出去,所以需要使用本地的全局配置settings;

另外,先配置snapshot版,发布后,再配置release版,但是实测release版使用Maven发布不了,失败,最后选择去官方发布

因此最终方案:

SNAPSHOT版本地Maven打包发布,RELEASE版则去Nexus官方仓库发布

  • 全局配置

    首先确定IDEA使用的是哪个Maven,File->settings->Build->Maven->User Settings files其路径下的settings确定好,去修改它

    • snapshot版

      <servers>
          <server>
              <id>ossrh</id>
              <!--确保此处输入的能登录sonatype账号-->
              <username>slipperySoap(SonaType账号)</username>
              <password>对应的sonatype账号密码</password>
          </server>
      </servers>
      
      <profiles>
          <profile>
              <id>ossrh</id>
              <activation>
                  <activeByDefault>true</activeByDefault>
              </activation>
              <properties>
                  <!--这里填安装的GnuPG位置-->
                  <gpg.executable>D:/GnuPG/bin/gpg.exe</gpg.executable>
                  <gpg.passphrase>填写生成秘钥时输入的密码Passphrase</gpg.passphrase>
                  <!--这里填秘钥在磁盘上的位置,可通过上面步骤的 gpg --list-keys找到-->
                  <gpg.homedir>C:/Users/slipperySoap/AppData/Roaming/gnupg</gpg.homedir>
              </properties>
          </profile>
      </profiles>
      
  • 局部配置

    在父项目的pom.xml下配置

    • snapshot版

      <!--gav信息-->
      <groupId>io.github.stupidSoap</groupId>
      <artifactId>jave</artifactId>
      <!--需要特别注意,上传的是SNAPSHOT仓库,所以此处版本号后缀必须带SNAPSHOT-->
      <version>1.0.2-SNAPSHOT</version>
      
      <!--项目信息...-->
      <name>jave</name>
      <description>official jave(Java Audio Video Encode) from www.sauronsoftware.it</description>
      <url>https://github.com/stupidSoap/jave</url>
      
      <!--开源协议...-->
      <licenses>
          <license>
              <name>The Apache Software License, Version 2.0</name>
              <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
          </license>
      </licenses>
      
      <!--开发者信息-->
      <developers>
          <developer>
              <id>slipperySoap</id>
              <name>slipperySoap</name>
              <email>slipperysoap@qq.com</email>
              <roles>
                  <role>Project Manager</role>
                  <role>Architect</role>
              </roles>
              <timezone>+8</timezone>
          </developer>
      </developers>
      
      <!--项目在github或其它托管平台的地址-->
      <scm>
          <connection>https://github.com/stupidSoap/jave.git</connection>
          <developerConnection>scm:git:ssh://git@github.com:stupidSoap/jave.git</developerConnection>
          <url>https://github.com/stupidSoap/jave</url>
      </scm>
      
      <profiles>
          <profile>
              <!--注意,此id必须与setting.xml中指定的一致,不要自作聪明改它名字-->
              <id>ossrh</id>
              <activation>
                  <activeByDefault>true</activeByDefault>
              </activation>
              <build>
                  <plugins>
                      <!--发布到中央SNAPSHOT仓库插件-->
                      <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>
      
                      <!--生成源码插件-->
                      <plugin>
                          <groupId>org.apache.maven.plugins</groupId>
                          <artifactId>maven-source-plugin</artifactId>
                          <version>2.2.1</version>
                          <executions>
                              <execution>
                                  <id>attach-sources</id>
                                  <goals>
                                      <goal>jar-no-fork</goal>
                                  </goals>
                              </execution>
                          </executions>
                      </plugin>
      
                      <!--生成API文档插件-->
                      <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>
      
                      <!--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>
      
              <distributionManagement>
                  <snapshotRepository>
                      <!--注意,此id必须与setting.xml中指定的一致-->
                      <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>
          </profile>
      
      </profiles>
      

注意:以上配置文件中的注释建议最后删除,有时候一些非半角字符会影响打包和发布,造成的意想不到的情况;实测确实如此,删除后错误解除,就没事了

打包发布

配置SNAPSHOT版之后,IDEA右侧Maven栏中先clean,再package,大概1-5秒,显示 BUILD SUCCESS即打包成功了,项目已经打包成了jar包在target编译目录中了

紧接着,进行发布,deploy,在发布过程中,会要求输入之前设置的gpg密钥密码,发布时间时间远比打包时间久,大概1分钟,显示BUILD SUCCESS即发布成功了,

可以去Nexus官网查看

可以不用登录查看,左侧Repositories点击后,再点Refresh,点选Snapshots,在下方,根据组号标识GroupId即可搜索到了

Nexus查询SNAPSHOT版发布

同时在发布后Maven本地仓库中,也自动按组号标识GroupId生成了对应的依赖

snapshot版发布后查看Maven本地仓库

正式发布

在Nexus官方发布RELEASE版本,还是在Nexus官网

发布RELEASE需要登录账号,还是sonatype的账号,但是实测在登录的时候一开始一直密码错误,过了差不多一个小时又突然能登录了,猜测是sonatype和nexus两个网站之间数据同步问题

登录后,发现左侧栏多出了一栏Build Promotion

选择Stagning Repositories,点Refresh刷新列表,显示出自己的sonatype仓库,勾选中,然后点Close进行关闭检测(正式发布前必须先close进行关闭检测),确认关闭后,查看Status状态由open变为closed后,再点击Release发布正式release正式版本

RELEASE版正式发布

点击关闭后会确认提示,Description啥也不用写,直接确认就行

确认关闭仓库

在sonatype仓库close之后,sonatype会认为用户马上去正式发布了,所以会发一份Bug检测的邮箱,如果没啥错误,就是这样的一份,提示Great Job no threats was found,就是没啥错,直译过来就是干得好,没发现威胁

release版本发布成功通知

自动发布

在Relese之后不久,官方检测到已经发布了snapshot和release两个版本,所以此时又发了一份邮件,提示

your component will be available to the public on Central https://repo1.maven.org/maven2/, typically within 30 minutes, though updates to https://search.maven.org can take up to four hours.

意思就是大约30分钟官方会自动将组件发布到中央仓库,但是要被其他可视化网站比如https://search.maven.org搜索到大约要4小时

自动上传中央仓库通知

收到这份邮件,基本任务已经大功告成了,就等官方了

实测,从下午4点等到晚上11点还是搜不到,第二天上午9点在mvnrepository搜了一下已经有了,所以大概要等一晚上的时间就能搜到了

通过中央仓库搜索到上传的依赖
完结撒花~~~🎉🎉🎉

参考文献

基于参考其他优秀博主的辛苦总结,加上自己的实践最后成功了,于是在此总结,十分感谢他们和CSDN社区


版权声明:本文为slipperySoap原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>