将自己的开源 jar 包上传至 Maven 中央仓库,其中还是有不少坑的,所一开一篇文章做下记录。
# 注册 sonatype 账号
- 进入 issues.sonatype.org 注册账号,基于这个平台才可以上传至
Maven仓库。![pPBJoeU.png]()
- 注册完成后需要记住
账号 密码,后面上传需要进行授权验证。
# 新建 Maven 项目工单
- 项目选择:
Community Support - Open Source Project Repository Hosting (OSSRH) - 问题选择:
New Project![pPBYSeO.png]()
Group Id: 推荐使用自己的域名,并遵循以下格式- 例如:
rainrem.top - 则填:
top.rainrem
- 例如:
Project URL: 项目地址SCM url: 项目克隆地址Username(s): 注册时的用户名![pPBtOr6.png]()
- 新建工单后等待管理员审核
- 问题 → 我的报告中查看
issue进度![pPBNseK.png]()
- 等待几分钟后,就会收到
OSSRH的回复,如下图![pPBN4yt.png]()
- 翻译为中文的报告显示
![pPBUbB6.png]()
- 自己的域名,则需要在域名解析中增加
TXT的解析![pPBU81A.png]()
- 如果是
io.github.xxx这种git域名,则需要新建完整公开的git仓库,如下两个图 (网上找的)![pPBUDpj.png]()
![pPBUr1s.png]()
- 然后点击
Respond按钮开启工单,让管理员去验证 - 等待回复,回复结果如下,就表示可以推送你的
jar包到仓库中了![pPBUXND.png]()
- 翻译为中文的报告显示
![pPBUx9H.png]()
# GPG 密匙处理
- 我们需要使用
gpg生成秘钥,在后续发布jar包时会根据生成的秘钥进行校验。 - 因为
sonatype也需要对上传这一行为进行权限的校验,避免恶意上传文件的行为。
# 安装 gpg
- 官网下载地址:www.gnupg.org
- Window 版下载地址:gpg4win-4.0.4.exe
- 下载完成后一路点击下一步即可完成安装。
# 创建秘钥
- 安装完成后,打开命令行执行下面命令来生成秘钥。
gpg --gen-key |
- 在生成秘钥的过程中,会要求输入姓名和邮箱地址。
- 在命令行窗口下填完这两个信息后,还会弹窗要求输入一个生成秘钥的密码,切记需要记住此密码下面会用到。
![pPBdbFO.png]()
- 填完后继续,秘钥就会成功生成并保存在本地目录下。
![pPBw9Tf.png]()
# 上传秘钥
- 我们需要把公钥上传至服务器供
sonatype验证,通过下面命令上传公钥。
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 你自己的秘钥 |
- 验证公钥是否成功上传至服务器
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys 你自己的秘钥 |

- 如果上传失败请更换服务器地址将
keyserver.ubuntu.com替换以下其中之一,全部都是11371的端口pool.sks-keyservers.nekeys.openpgp.orgpgp.mit.edu
- 这些公钥服务器间会同步它们的数据给其他服务器,所以只要上传成功到其中一台可以。
# settings.xml 配置
- 如果不知道
Maven的settings.xml
的位置,打开IDEA→文件→设置→构建、执行、部署→构建工具→Maven - 查看
Maven主路径,如果是Bundled (Maven 3),settings.xml的位置则在你安装IDEA
路径下的→plugins→maven→lib→maven3→conf文件夹下 - 例如:
C:\LightRainData\IDEA\IntelliJ IDEA 2023.1.2\plugins\maven\lib\maven3\conf
<!-- 在 settings.xml 中的 servers 节点下添加 --> | |
<server> | |
<!-- 此处 id 需要和 pom.xml 中配置的 serverId 保持一致 --> | |
<id>ossrh</id> | |
<!-- 配置你注册 issues.sonatype.org 的账号密码 --> | |
<username>LightRain</username> | |
<password>xxx</password> | |
</server> |
<!-- 在 settings.xml 中的 profiles 节点下添加 --> | |
<profile> | |
<!-- 此处 id 需要和 pom.xml 中配置的 serverId 保持一致 --> | |
<id>ossrh</id> | |
<activation> | |
<activeByDefault>true</activeByDefault> | |
</activation> | |
<properties> | |
<gpg.executable>gpg</gpg.executable> | |
<!-- 生成秘钥时填写的密码 --> | |
<gpg.passphrase>2qmT84jWycBh</gpg.passphrase> | |
</properties> | |
</profile> |
- 以下为
settings.xml的全部配置
<?xml version="1.0" encoding="UTF-8"?> | |
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0" | |
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 http://maven.apache.org/xsd/settings-1.2.0.xsd"> | |
<pluginGroups></pluginGroups> | |
<proxies></proxies> | |
<servers> | |
<server> | |
<!-- 此处 id 需要和 pom.xml 中配置的 serverId 保持一致 --> | |
<id>ossrh</id> | |
<!-- 配置你注册 issues.sonatype.org 的账号密码 --> | |
<username>LightRain</username> | |
<password>xxx</password> | |
</server> | |
</servers> | |
<mirrors> | |
<mirror> | |
<id>maven-default-http-blocker</id> | |
<mirrorOf>external:http:*</mirrorOf> | |
<name>Pseudo repository to mirror external repositories initially using HTTP.</name> | |
<url>http://0.0.0.0/</url> | |
<blocked>true</blocked> | |
</mirror> | |
</mirrors> | |
<profiles> | |
<profile> | |
<!-- 此处 id 需要和 pom.xml 中配置的 serverId 保持一致 --> | |
<id>ossrh</id> | |
<activation> | |
<activeByDefault>true</activeByDefault> | |
</activation> | |
<properties> | |
<gpg.executable>gpg</gpg.executable> | |
<!-- 生成秘钥时填写的密码 --> | |
<gpg.passphrase>2qmT84jWycBh</gpg.passphrase> | |
</properties> | |
</profile> | |
</profiles> | |
</settings> |
- 将修改完成后的
settings.xml保存。- 修该
IDEA中Maven下的settings.xml路径指向 - 或将
settings.xml复制一份到User用户下的.m2文件夹下 - 例如:
C:\User\LightRain\.m2\settings.xml![pPBsNF0.png]()
- 修该
# 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 一定要和你申请工单的 groupId 保持一致 --> | |
<groupId>top.rainrem</groupId> | |
<!-- 项目名称 --> | |
<artifactId>toolbox</artifactId> | |
<!-- 版本号 --> | |
<version>1.0.0-RELEASE</version> | |
<!-- 名称 --> | |
<name>toolbox</name> | |
<!-- 描述 --> | |
<description>工具</description> | |
<properties> | |
<!-- 项目使用的 java 版本 --> | |
<java.version>17</java.version> | |
<maven.compiler.source>17</maven.compiler.source> | |
<maven.compiler.target>17</maven.compiler.target> | |
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
<!-- 项目仓库地址,根据实际情况修改 --> | |
<projectUrl>https://gitee.com/RainSauce/toolbox.git</projectUrl> | |
<!-- serverId 配置,需要和 settings.xml 中 servers.server.id 保持一致 --> | |
<serverId>ossrh</serverId> | |
</properties> | |
<!-- 开发者信息 --> | |
<developers> | |
<developer> | |
<name>LightRain</name> | |
<email>3164395730@qq.com</email> | |
<url>${projectUrl}</url> | |
</developer> | |
</developers> | |
<url>${projectUrl}</url> | |
<!-- 许可证信息,这里是 Apache 2.0 的许可证,大家根据实际情况修改 --> | |
<licenses> | |
<license> | |
<name>The Apache Software License, Version2.0</name> | |
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url> | |
<distribution>repo,manual</distribution> | |
</license> | |
</licenses> | |
<scm> | |
<!-- 采用 projectUrl 变量代替这个值,方便给重复利用这个配置,也就是上面的标签替换一下值就行 --> | |
<connection>${projectUrl}</connection> | |
<developerConnection>${projectUrl}</developerConnection> | |
<url>${projectUrl}</url> | |
</scm> | |
<distributionManagement> | |
<snapshotRepository> | |
<!-- 这个 id 和 settings.xml 中 servers.server.id 要相同,因为上传 jar 需要登录才有权限 --> | |
<id>${serverId}</id> | |
<name>OSS Snapshots Repository</name> | |
<!-- 官方仓库地址不需要修改 --> | |
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url> | |
</snapshotRepository> | |
<repository> | |
<!-- 这个 id 和 settings.xml 中 servers.server.id 要相同,因为上传 jar 需要登录才有权限 --> | |
<id>${serverId}</id> | |
<name>OSS Staging Repository</name> | |
<!-- 官方仓库地址不需要修改 --> | |
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url> | |
</repository> | |
</distributionManagement> | |
<dependencies> | |
<!-- 此处坐标依赖自己决定添加 --> | |
</dependencies> | |
<!-- 打包及插件信息 --> | |
<!-- 这些配置基本不用修改,原样粘贴进去即可 --> | |
<!-- 如果 plugins 中的坐标爆红,将其添加到 dependencies 中完成拉去即可解决 --> | |
<!-- 其中 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> | |
</project> |
- 需要注意的地方:
snapshotRepository是项目快照版本snapshot上传地址,如果项目的版本号,如:1.0.0-SNAPSHOT,会上传到这个仓库。- 通常情况下
repository是我们真正需要发布项目的远程仓库上传地址。需要注意的是我们这里写的是staging
暂存地址,而不是release版本的地址。(为什么这么做?后文详述) - 我们上传的远程仓库的地址是带
s01前缀的,而比较旧的文章中不带s01前缀。 - 因为旧的
sonatypemaven仓库已经资源满了,官方新建了一个s01maven仓库。 - 现阶段在
sonatypeJIRA管理平台上注册的用户,只能上传这个新的s01仓库。
# 打包上传
- 在项目根目录下,运行下面的命令进行
maven打包操作 (同时将项目jardeploy到远程maven仓库)。 - 在打包运行过程中,会弹出一个对话框提示你输入密钥
Passphrase,输入上文gpg生成秘钥的密码即可。 -Dmaven.test.skip=true表示跳过测试代码
mvn clean install deploy -P release -Dmaven.test.skip=true |

- 需要注意的是:
- 不要使用
IDEA的maven打包,IDEA的maven打包会报错,无法执行gpg
命令,至于为什么我也不清楚,使用上文的CMD命令行打包即可。 - 使用
mvn命令行打包的时候,需要注意你的JAVA_HOME环境变量的指向,是不是你期望的版本。 - 如果
maven depoly发布命令报401 authentication错误,是因为你的maven的setting.xml
的server配置的用户名密码错误,或者setting.xml的server配置id与pom
里面配置的repository id不一致导致的。 - 也有可能你的电脑上
maven多个版本,项目使用的不是同一个setting.xml。 - 如果报
400错误,很有可能是你已经上传过的 jar,同一个版本再次重复上传了。
- 不要使用
- 如果使用
mvn命令时出现 mvn 不是内部或外部命令←请点击查看![pPB6e8f.png]()
- 上传成功后,可在官网查看到 Nexus Repository Manager
![pPBR0l6.png]()
- 并且在
OSSRH中也能收到反馈。![pPB27J1.png]()
# 同步到中央仓库
- 上面的步骤只是把项目传到了
sonatype上了,还没有发布出去,中央仓库中还不存在。 - 进入 Nexus Repository Manager 使用在 sonatype 注册的账号登录即可。
- 点击旁边的
Staging Repositories即可看到我们上传的项目。![pPB2PrF.png]()
![pPB2kVJ.png]()
![pPB2Aa9.png]()
- 点击
Refresh按钮刷新查看Release按钮是否可以点击![pPB2WsU.png]()
- 只要确认同步到
Maven中央仓库中你就无法进行修改和删除这是为了保护稳定性,但你可以发布新版本。 - 然后就是等待就可以了!
- 账号密码和上面注册的
ossrh一致 - https://s01.oss.sonatype.org
- 一般
30分钟后能查看 - https://repo1.maven.org/maven2/
- 一般
4小时后能查看 - https://search.maven.org/
- 一般
24小时后能查看 - https://mvnrepository.com/
- 账号密码和上面注册的
- 一切都
OK之后,最好回到sonatype JIRA管理平台将 “问题” 关闭,这样sonatype JIRA管理流程就全部完成了。
# 总结
以后发布项目,如果 groupId 不变的话,我们就不需要再去申请工单了。
上述 settings.xml 已经配置了 servers ,就不用再次配置了,即第二步配置 settings.xml 可以省略了。
秘钥也已经生成过了,也不需要再次生成了, 即第三步的秘钥生成也不需要了。
不过如果更换了电脑,那就要重新配置 settings.xml 并重新生成并上传秘钥了。





















