Administrator
Administrator
发布于 2023-10-27 / 61 阅读
0
0

maven发布jar到中央仓库

说明

很多时候,我们开发的构件需要上传到maven私服,以便团队中其他人使用。但在开源社区,例如github上托管的项目,如果希望给其他人使用就不能发布到私服了,最好的选择当然是maven官方的中央仓库。具体怎么做呢?

操作步骤

操作步骤宏观上大致分为三个: 1. 官方工单申请;2,gpg密钥设置和公钥上传 2. 项目配置(setting.xml和pom.xml);3. 执行发布

官方工单申请

官方工单申请地址为: issues.sonatype.org
若未注册,需要先注册。注册后的具体步骤网上教程很多,可以参考这篇:一键搞定发布自己Jar到Maven中央仓库

这里有几点注意事项:

  1. 工单处理时效还是蛮快的,几个小时或次日就有消息了。
  2. 我开始groupId随便取的,没通过,他评论建议我使用io.github.*, 因此我使用了io.github.pengxianggui
  3. 工单里的groupId必须和pom.xml中的groupId保持一致,否则后续推不上去(为此我改了项目中的groupId)。
  4. groupId非常重要,一旦审核通过就改不了,要改只能重新提单子。所以非必要不要变。
  5. 工单审核通过后,评论里会给进一步的指导。
  6. 审核通过后,别忘了关闭工单。
  7. sonatype的账密千万别忘了,后面要配置到settings.xml里的。

这是我操作时申请的工单,可以参考。

gpg密钥配置

gpg的作用大概是为你的构件(jar)进行加密,防止deploy传输中被篡改。

安装

因为我是mac, 命令行可以直接安装: brew install gpg2。如果是win,可以下载后安装(可参考上面那篇博客)。
我安装后的效果

也可以下载后安装,这里附上下载地址和操作指南: mac获取maven-gpg-key, 操作指南基本也是下面命令行的可视化替代而已。

❗️ 注意: 如果使用上面下载的软件可视化操作,下面这些命令行步骤就可以跳过了。

生成密钥

gpg --gen-key

会提醒你输入姓名、邮箱、密码等。输入后,直接回车。

命令查看密钥

gpg --list-keys
image-1698452051190

可以看到,我刚刚生成的密钥,pub 下 一串16进制数是密钥ID。

上传至公钥服务器

gpg --keyserver keyserver.ubuntu.com --send-keys 秘钥ID
通过这句命令将指定的密钥对应的公钥上传至公钥服务器。

❗️注意:这个命令可能会失败。或是网络问题,或是这个地址不可用。这时有个备用方法,那就是直接到https://keyserver.ubuntu.com/# 去,在页面上上传公钥。

具体操作如下:
image-1698452624654
image-1698452748690

❓上面的那一大串公钥是哪里来的呢?使用下面的命令查看密钥的公钥:
gpg -a -o public.key --export 密钥ID
公钥会被导出到public.key,用文本编辑器查看复制出来,就是上面的一大串内容了。

❗️注意: 上传完毕后,要确认下能否查到。具体方法:
访问这个地址: https://keys.openpgp.org, 然后输入你刚刚填写的邮箱,即可查询。
image-1698711516254
image-1698711545641

上图中马赛克遮住的部分其实就是上面的密钥ID。

至此,gpg准备部分就算了结了。

上面讲的两种方式,更推荐下载软件安装的方式,而不是命令行。原因有二:

  1. 上传公钥时,可以直接在软件里自动提示你完整,一个按钮即可,不会有网络问题;
  2. 可以方便的设置过期时间;

项目配置(setting.xml和pom.xml)

settings.xml配置

<!-- 针对特定服务器指定认证信息。ossrh是Sonatype OSS Repository Hosting的简称。
在应用此settings.xml的项目的pom.xml中,distributionManagement里需要保证id相同。
才能在发布时应用此账密。 -->
<server>
  <id>ossrh</id>
  <!-- 下面的账密,必须是之前在sonatype里注册的 -->
  <username>******</username>
  <password>******</password>
</server>

<profiles>
    <!-- 发布到maven中央仓库。项目install时需勾选ossrh, 才能deploy到中央仓库 -->
    <profile>
      <!-- 这个id值其实跟上面的server里的id不必相同 -->
      <id>ossrh</id>
      <!-- 这里设置这些properties是为了pom.xml中引用  -->
      <properties>
        <!-- 这是利用gpg插件加密时调用gpg的命令 -->
        <gpg.executable>gpg2</gpg.executable>
        <!-- 前面生成gpg密钥ID时设置的密码,如果不设置这个,执行时会交互式让你输入密码 -->
        <gpg.passphrase>***</gpg.passphrase>
        <!-- 前面生成的gpg 密钥对应的签名短 keyid,如何获取看下面批注 -->
        <gpg.keyname>***</gpg.keyname>
        <!-- gpg密钥文件位置,一般默认为 ~/.gnupg,保险起见填写绝对路径 -->
        <gpg.homedir>/Users/pengxianggui/.gnupg</gpg.homedir>
      </properties>
    </profile>
</profiles>

❗️【注意】:

  1. 上面profiles的内容也可以写到pom.xml里。但是考虑到其中有gpg的一些敏感信息,写到settings.xml里了。
  2. 上面gpg.keyname的值如何获取呢,可以看官网说明, 重点看下面截图这个部分:
    image-1698666049566

pom.xml 配置

如果要上传maven中央仓库,pom.xml里有几个部分是非常重要的(必不可少):

  1. description和url必不可少
  2. licenses: 指定项目的开源许可证信息。
  3. scm: 主要作用是指定项目的源代码版本控制系统,以便maven插件与版本控制系统交互,执行一些与版本控制相关的操作。这些操作包括标记版本、生成发布说明、检查出指定版本等。
  4. developers: 指定开发者信息。
  5. distributionManagement: 用于配置如何分发项目构建产物(例如 JAR 文件)到不同的 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>io.github.pengxianggui</groupId>
    <artifactId>db-metadata-parent</artifactId>
    <version>2.4.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>db-metadata-parent</name>
    <description>A Low-code development framework base on data-drive</description>
    <url>https://github.com/pengxianggui/db-metadata</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- 指定maven编译的java项目是java8。有这两个,一般就无需 maven-compiler-plugin了 [start]-->
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- ********************************************************************* [end]-->
    </properties>

    <modules>
        <module>./db-metadata-interface</module>
        <module>./db-metadata-server-springboot</module>
        <module>./db-metadata-analysis-springboot</module>
        <module>./db-metadata-extends</module>
    </modules>

    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
            <distribution>repo</distribution>
        </license>
    </licenses>
    <scm>
        <connection>scm:git:git@github.com:pengxianggui/db-metadata.git</connection>
        <developerConnection>scm:git:git@github.com:pengxianggui/db-metadata.git</developerConnection>
        <url>https://github.com/pengxianggui/db-metadata</url>
        <tag>v@{project.version}</tag>
    </scm>
    <developers>
        <developer>
            <name>XiangGui Peng</name>
            <email>pengxianggui@outlook.com</email>
            <timezone>+8</timezone>
        </developer>
    </developers>

    <pluginRepositories>
        <pluginRepository>
            <id>maven-ali</id>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

    <!-- 配置maven远程仓库,若本地找不到,则会从这里配置的远程仓库寻找依赖,最后是中央仓库 -->
    <repositories>
        <repository>
            <id>maven-ali</id>
            <name>阿里云远程maven仓库</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
            <layout>default</layout> <!--用于定位和排序构件的仓库布局类型-可以是default(默认)或者legacy(遗留)-->
            <releases>
                <enabled>true</enabled> <!--可从此仓库下载releases版本的依赖-->
            </releases>
            <snapshots>
                <enabled>false</enabled> <!--禁止从此仓库下载shapshots版本的依赖,公共仓库的snapshot版本往往不稳定且不受控制-->
                <!--                <updatePolicy>always</updatePolicy>--> <!-- 上面设置为false后,这两条配置就没意义了,注释掉 -->
                <!--                <checksumPolicy>warn</checksumPolicy>-->
            </snapshots>
        </repository>
    </repositories>

    <!-- 配置打包发布的远程仓库 -->
    <distributionManagement>
        <snapshotRepository>
            <id>ossrh</id>
            <name>Sonatype Nexus Snapshots</name>
            <url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
        </snapshotRepository>
        <repository>
            <id>ossrh</id>
            <name>Nexus Release Repository</name>
            <url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
        </repository>
    </distributionManagement>

    <build>
        <pluginManagement>
            <plugins>
                <!-- 生成项目的源代码 JAR 文件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-source-plugin</artifactId>
                    <version>3.2.1</version>
                    <configuration>
                        <attach>true</attach>
                    </configuration>
                    <executions>
                        <execution>
                            <id>attach-source</id>
                            <phase>compile</phase>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- javadoc文档生成插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <version>3.4.0</version>
                    <configuration>
                        <!-- jdk1.8要加上: 防止注释中的非标准标记(如@date) -->
                        <additionalJOptions>
                            <additionalJOption>-Xdoclint:none</additionalJOption>
                        </additionalJOptions>
                    </configuration>
                    <executions>
                        <execution>
                            <id>attach-javadocs</id>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- release plugin,用于发布到release仓库部署插件 -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-release-plugin</artifactId>
                    <version>3.0.1</version>
                    <configuration>
                        <tagNameFormat>v@{project.version}</tagNameFormat>
                        <autoVersionSubmodules>true</autoVersionSubmodules>
                        <arguments>-DskipTests</arguments>
<!--                        &lt;!&ndash;   手动push。 release:prepare执行时总是无法自动push代码,这里改为手动。在-->
<!--                                release:prepare 执行完毕后,手动push(tag也要), 再执行 release:perform&ndash;&gt;-->
<!--                        <pushChanges>false</pushChanges>-->
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
            </plugin>
            <!-- gpg加密 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-gpg-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <id>sign-artifacts</id>
                        <phase>verify</phase>
                        <goals>
                            <goal>sign</goal>
                        </goals>
                        <configuration>
                            <keyname>${gpg.keyname}</keyname>
                            <passphrase>${gpg.passphrase}</passphrase>
                            <passphraseServerId>${gpg.keyname}</passphraseServerId>
                            <gpgArguments>
                                <arg>--pinentry-mode</arg>
                                <arg>loopback</arg>
                            </gpgArguments>
                            <homedir>${gpg.homedir}</homedir>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- 自动close、release -->
            <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>
        </plugins>
    </build>
</project>

完整的pom.xml可以查看这里: pom.xml

重点关注我的pom里关于上面提到的这些部分。另外我的pom.xml里还涉及到maven-release-plugin的应用,关于这个插件,我也摸索了一遍,踩了些坑,后面单独篇幅去记录。

使用

上面的步骤就已经完成了所有准备了。接下来,就运行clean deploy发布就行了!具体操作就一句话:
勾选ossrh,点选clean和deploy,然后run即可,图示:
image-1698712352169

勾选ossrh的目的是为了应用settings.xml里那个id为ossrh的profile的配置

踩坑

  1. 工单填写时设置的groupId不能太随意,是有限制的,而且必须和项目里的groupId完全一致。
  2. gpg那个步骤省不了,但是我似乎发现发布SNAPSHOT版本时可以不要那个步骤(这一点没有确认过,不过这个总归省不了的)
  3. gpg公钥上传死活上不去,命令行各种报错,什么“No route", 或者网络问题… 最后是一个文章里找到的,可以在页面上传这个公钥,才解决问题。感谢那位不知名博主!(找不到记录了)。但后来抱着死磕的态度,又试了一次下载软件,相当顺利,所以更推荐下载软件。
  4. pom.xml里scm里的那几个url不要写错了,或者乱写;project下的description和url一定要写;
  5. pom.xml里的distributionManagement中的id一定要和settings.xml里配置的server那个匹配。相当于通过这个id,将pom.xml里的地址,和settings.xml里的账密对应上。maven才能正确使用账密去发布到这个地址。并且snapshotRepository和repository的id可以相同。
  6. 发布成功后,不是立马就能在maven中央仓库看到的,需要等几个小时。国内镜像就更延迟一些了。
  7. 上面pom.xml里nexus-staging-maven-plugin这个插件的作用自动close、release和drop。如果autoReleaseAfterClose设置为false, 或者仓库那边验证失败, 可能需要登录https://s01.oss.sonatype.org/#stagingRepositories手动操作。
  8. https://s01.oss.sonatype.orghttps://oss.sonatype.org 有什么区别?其实只是多个节点而已,可能以后还会有s02, s03,至于用哪个地址,取决于jira工单审核通过后,他给你的评论里,会告诉你地址的。那么pom.xml里就统一用这个地址。
  9. nexus sonatype manager 的登录也是一样的,jira里给你的是哪个地址,你也得登录哪个地址去管理。比如给我的是https://s01.oss.sonatype.org,我后来不小心登录了https://oss.sonatype.org,死活登录不上,提示账密错误或者无权限,折腾半天。

参考

  1. 一键搞定发布自己Jar到Maven中央仓库
  2. 如何将artifact发布到Maven中央仓库
  3. mac获取maven-gpg-key
  4. 如何提交自己的项目到Maven公共仓库
  5. Sign artifacts with GnuPG
  6. Maven-Java开源类库传至Maven中央仓库
  7. maven官方文档: GPG
  8. Deploying to OSSRH with Apache Maven

评论