将自己的开源 jar 包上传至 Maven 中央仓库,其中还是有不少坑的,所一开一篇文章做下记录。
# 注册 sonatype 账号
- 进入 issues.sonatype.org 注册账号,基于这个平台才可以上传至
Maven
仓库。 - 注册完成后需要记住
账号 密码
,后面上传需要进行授权验证。
# 新建 Maven 项目工单
- 项目选择:
Community Support - Open Source Project Repository Hosting (OSSRH)
- 问题选择:
New Project
Group Id
: 推荐使用自己的域名,并遵循以下格式- 例如:
rainrem.top
- 则填:
top.rainrem
- 例如:
Project URL
: 项目地址SCM url
: 项目克隆地址Username(s)
: 注册时的用户名- 新建工单后等待管理员审核
- 问题 → 我的报告中查看
issue
进度 - 等待几分钟后,就会收到
OSSRH
的回复,如下图 - 翻译为中文的报告显示
- 自己的域名,则需要在域名解析中增加
TXT
的解析 - 如果是
io.github.xxx
这种git
域名,则需要新建完整公开的git
仓库,如下两个图 (网上找的) - 然后点击
Respond
按钮开启工单,让管理员去验证 - 等待回复,回复结果如下,就表示可以推送你的
jar
包到仓库中了 - 翻译为中文的报告显示
# GPG 密匙处理
- 我们需要使用
gpg
生成秘钥,在后续发布jar
包时会根据生成的秘钥进行校验。 - 因为
sonatype
也需要对上传这一行为进行权限的校验,避免恶意上传文件的行为。
# 安装 gpg
- 官网下载地址:www.gnupg.org
- Window 版下载地址:gpg4win-4.0.4.exe
- 下载完成后一路点击下一步即可完成安装。
# 创建秘钥
- 安装完成后,打开命令行执行下面命令来生成秘钥。
gpg --gen-key |
- 在生成秘钥的过程中,会要求输入姓名和邮箱地址。
- 在命令行窗口下填完这两个信息后,还会弹窗要求输入一个生成秘钥的密码,切记需要记住此密码下面会用到。
- 填完后继续,秘钥就会成功生成并保存在本地目录下。
# 上传秘钥
- 我们需要把公钥上传至服务器供
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.ne
keys.openpgp.org
pgp.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
- 修该
# 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
前缀。 - 因为旧的
sonatype
maven
仓库已经资源满了,官方新建了一个s01
maven
仓库。 - 现阶段在
sonatype
JIRA
管理平台上注册的用户,只能上传这个新的s01
仓库。
# 打包上传
- 在项目根目录下,运行下面的命令进行
maven
打包操作 (同时将项目jar
deploy
到远程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 不是内部或外部命令←请点击查看 - 上传成功后,可在官网查看到 Nexus Repository Manager
- 并且在
OSSRH
中也能收到反馈。
# 同步到中央仓库
- 上面的步骤只是把项目传到了
sonatype
上了,还没有发布出去,中央仓库中还不存在。 - 进入 Nexus Repository Manager 使用在 sonatype 注册的账号登录即可。
- 点击旁边的
Staging Repositories
即可看到我们上传的项目。 - 点击
Refresh
按钮刷新查看Release
按钮是否可以点击 - 只要确认同步到
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
并重新生成并上传秘钥了。