之前的文章介绍了如何编写一个Maven插件。那插件的使用上呢?在本地,我们可以安装到本地仓库,使用没问题;在SIT环境中,我们可以安装到公司内部的私有仓库中。但如果公司的Maven包尚未形成规模,不需要搭建私有仓库,且私有仓库需要有专人进行维护,如果只有少量包,可能过一段时间都忘了还有这么个东西。等到出问题了找半天,又是一个麻烦事。

上传到Maven中央库也许是一个非常好的选择,任何人在任何地方都可以使用该包,爽歪歪。

为了方便,使用OSSRH的发布方案。

步骤介绍

整个步骤大致有如下三步

  • 使用JIRA申请创建一个新的Repository,用于在OSSRH申请空间。
  • 向项目的pom.xml中增加必要的内容
  • 部署

其中第一步需要人工审核,时间耗费比较久,按照个人经验来说半天可以搞定。

说明:如下步骤是OSSRH Guide的实践。

仓库及空间申请

创建JIRA账号

登录Snaptype JIRA

maven中央仓库和阿里 发布maven中央仓库_maven


收到邮件代表创建成功。

新建工单

再次登录Snaptype JIRA

依次填入概要、Group Id、Project URL(项目URL,可填github项目主页)、SCM url(项目版本控制链接)

maven中央仓库和阿里 发布maven中央仓库_xml_02


工单创建成功后需要等待邮件确认,反复几个来回后才能正常发布。下图是截止申请成功的所有交流。可以看到会有如下几个步骤

  • 创建工单
  • 在自己的github主页下创建一个它要求的repository以完成验证
  • 验证完成,允许用户发布组件到仓库
  • 申请的Group Id激活,用户发布的组件能够被同步到中央仓库(但要花两个小时)

maven中央仓库和阿里 发布maven中央仓库_maven_03

GPG签名准备

组件发布之前,需要进行GPG签名,发布到服务器后,服务器会使用公钥对组件进行校验。关于GPG的介绍和详细解读,大家可以参考这篇文章。这里涉及到几个点

  • 安装gnupg工具
# 安装
$ sudo apt install gnupg
# 安装成功与否的验证
$ gpg --version
gpg (GnuPG) 2.2.4
libgcrypt 1.8.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 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: /home/floyd/.gnupg
支持的算法:
公钥: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
密文: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
    CAMELLIA128, CAMELLIA192, CAMELLIA256
散列: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
压缩: 不压缩, ZIP, ZLIB, BZIP2
  • 生成密钥对
# 执行如下命令,提示填入真实姓名和邮箱,并设置密码
$ gpg --gen-key
# 查看刚才生成的密钥
$ gpg --list-key
/home/floyd/.gnupg/pubring.kbx
------------------------------
pub   rsa3072 2020-02-29 [SC] [有效至:2022-02-28]
      EB3877C670A794E0238E66E1D4420641AADB285E
uid           [ 绝对 ] Zou Guodong <zou894475@gmail.com>
sub   rsa3072 2020-02-29 [E] [有效至:2022-02-28]

上面生成的秘钥,其中EB3877C670A794E0238E66E1D4420641AADB285E是用户ID,记住,下一步会使用

  • 发送公钥到 key server
    这一步非常重要,否则OSSRH会因为无法验证发布的组件而导致发布失败。
gpg --send-key EB3877C670A794E0238E66E1D4420641AADB285E

如果发送成功,你可能会收到opengpg发送的邮件

maven中央仓库和阿里 发布maven中央仓库_maven_04


但这一步很可能会遇到问题,这在后面的问题集中有介绍

  • 在pom.xml中配置插件(在POM修改中有对应说明)
  • 在setting.xml中配置要使用的gpg工具 (在setting.xml修改中有对应说明)

pom.xml修改

添加POM必备项

  • 项目基础信息
<groupId>com.example.applications</groupId>
<artifactId>example-application</artifactId>
<version>1.4.7</version>

<name>${project.groupId}:${project.artifactId}</name>
<description>A application used as an example on how to set up pushing   its components to the Central Repository.</description>
<url>http://www.example.com/example-application</url>
  • 证书
<licenses>
  <license>
    <name>The Apache License, Version 2.0</name>
    <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
  </license>
</licenses>
  • 开发者信息
<developers>
    <developer>
      <name>Manfred Moser</name>
      <email>manfred@sonatype.com</email>
      <organization>Sonatype</organization>
      <organizationUrl>http://www.sonatype.com</organizationUrl>
    </developer>
  </developers>
  • SCM信息
    即版本控制信息
<scm>
  <connection>scm:git:git://github.com/simpligility/ossrh-demo.git</connection>
  <developerConnection>scm:git:ssh://github.com:simpligility/ossrh-demo.git</developerConnection>
  <url>http://github.com/simpligility/ossrh-demo/tree/master</url>
</scm>

添加发布相关插件

  • Javadoc 和 源码打包插件
<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>
    <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>
  • Nexu暂存插件
<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://oss.sonatype.org/</nexusUrl>
     <autoReleaseAfterClose>true</autoReleaseAfterClose>
  </configuration>
</plugin>

Setting.xml修改

JIRA账号

设置准备阶段设置的账号密码,以便mvn能够连接到服务器

<settings>
  <servers>
    <server>
      <id>ossrh</id>
      <username>your-jira-id</username>
      <password>your-jira-pwd</password>
    </server>
  </servers>
</settings>

GPG

添加如下配置,指定加密工具

<settings>
  <profiles>
    <profile>
      <id>ossrh</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <gpg.executable>gpg</gpg.executable>
        <gpg.passphrase>the_pass_phrase</gpg.passphrase>
      </properties>
    </profile>
  </profiles>
</settings>

我的配置

作为参考,给出我的配置,看这里

发布

上述内容准备好后,可以执行如下命令进行发布。

mvn clean deploy

需要注意的是,如果我们发布的版本是release版本,即版本号不以-SNAPSHOT结尾,且刚才配置的Nexus暂存插件的autoReleaseAfterClose设置为true时,执行上述命令后,OSSRH会自动发送到中央库。

至此,发布完成。更多步骤请参考官方文档。官方文档中提供了完整的发布开发版、release版的方式,可供参考。

效果

执行成功,等待大约两个小时,你就能在中央库查询到自己的组件了。例如搜索我刚才发布的组件。

maven中央仓库和阿里 发布maven中央仓库_xml_05


点击进入,可以查看详情,这里

maven中央仓库和阿里 发布maven中央仓库_xml_06


而作为一个插件,可以通过如下方式使用它

<plugin>
        <groupId>com.github.zou8944</groupId>
        <artifactId>json-loader-maven-plugin</artifactId>
        <version>1.0.0</version>
        <executions>
          <execution>
            <phase>initialize</phase>
            <goals>
              <goal>read-project-json-to-properties</goal>
            </goals>
            <configuration>
              <files>
                <file>hello.json</file>
              </files>
            </configuration>
          </execution>
        </executions>
      </plugin>

踩过的坑

  • 在snatype上无法找到对应的profile

    该问题是由于pom的GroupId和第一步申请JIRA账号时指定的GroupId不一致导致,修改本地使得一致即可
  • 组件上传成功,但服务端签名校验失败

    该问题在于没有上传本地生成的密钥对。执行gpg --send-key <ID>生成即可。上传后,收到opengpg发来的邮件才能确认上传成功。
  • pgp上传秘钥失败
    前后报过两个错,分别是上传失败和服务器拒绝连接。网上找了很多解决方案对我都无效。最终使用如下终极方法
# 删除整个.gnupg目录
sudo rm -r ~./gnupg
# 重新生成秘钥,不能加sudo
gpg --gen-key
# 执行如下命令,这是解决服务器拒绝连接的关键
pkill dirmngr
# 再次发送
gpg --send-key <ID>

总结

本文主要以实践为主,介绍了如果将本地项目发布到Maven中央库。尽管没有什么原创的内容,但价值在于踩坑。

参考文档

  1. Guide to uploading artifacts to the Central Repository
  2. How to Publish a Java Library to Maven Central
  3. OSSRH Guide
  4. gnupg can not connet to key server
  5. pgp can not find secret key