发布了一个jar包到中央仓库,我的心好累…
原创:微信公众号
码农参上,欢迎分享,转载请保留出处。
哈喽大家好啊,我是Hydra。
前几天我在网上冲浪的时候,看见有一个老铁在git上给我提了一个issue:

万万没想到,有一天我写的烂代码居然也会被要求提到中央仓库…
话再说回来,发布jar包到中央仓库这个事,也不是我不想,而是真的不会啊!
不过既然铁子们都开口了,我这硬着头皮也得上不是?那么从网上翻翻文档,正式开搞。

Sonatype
首先第一步,我们需要在sonatype上注册账号并提交一个issue。
sonatype这个名字,突然一说大家可能有点反应不过来,但是看完下面这张图大家应该就明白了:

没错,如果各位所在的公司有搭建自己的maven私服的话,那么一般用的就是sonatype公司开发的Nexus了。
这时候有小伙伴们估计就要问了,那么我要上传中央仓库和你sonatype又有什么关系?

这是因为sonatype提供了一个服务,英文全称是Open Source Software Repository Hosting,翻译过来可以理解为开源软件资源库托管服务,简称为OSSRH。
开发者在把自己的开源项目打成jar包后,可以免费地将jar包托管在这里,这里先记住OSSRH这个简称,后面很多地方还会用到。
并且,maven中央仓库是不允许我们直接上传jar包到它上面的,因此我们只能将jar包发布到它指定的第三方maven仓库,然后这个仓库再将jar包同步到中央仓库。而sonatype的OSSRH仓库就是被认可的第三方仓库之一,所以我们选择把jar包先发布到这上面来。
1、注册
铺垫了这么多,回过头来注册sonatype的账号,注册地址:
注册比较简单,填一下邮箱、姓名、用户名和密码后,点击sign up就完成了。

2、提交issue
登录完成后,语言可以选择中文,在system dashboard页面中,点击上方导航栏上的新建按钮,就可以创建一个issue,我看也有地方把这个issue称为工单。
要填的东西有点多,我们分两页看,先看第一页:

- 项目:选择
Community Support - Open Source Project Repository Hosting (OSSRH) - 问题类型:选择
New Project - 概要:项目概要,这里填写项目名称就行,如果更严谨的话,可以说明是要新发布一个包到maven
- 描述:非必填项,这里简单描述了一下项目的功能
填完这些后,接着填下面的内容:

Group Id:项目的groupId。如果以com等开头的话,之后会验证你对该域名的所有权。所比较简单的做法是直接以io.github.开头,再加上你的github的用户名,所以这里我填写的是io.github.trunks2008Project URL:项目地址,不带.git结尾SCM url:也是项目地址,不过最后要带上.gitUsername(s):非必填项,这里是能辅助你提交项目的合作人的帐号,前提是他也在这个JIRA注册过账号Already Synced to Central:这里选择No,如果选Yes会关闭自动同步到中央仓库
填写完成后,点新建按钮就完成了issue的提交。
3、创建临时库
创建完issue后等个几分钟,在它的活动日志区就会收到一条回复:

大意就是,如果想要继续流程的话,就按照下面两步走。
首先,先到你的github账户下面,按照它指定的名称,建这么一个临时仓库,证明你对这个github账号的所有权。于是我麻利的在github建好了这个仓库:

然后问题就来了,我们仔细看看回复中的第二步指南:
Edit this ticket and set Status to Open.
翻译过来就是,编辑这个票据并把状态设置为打开状态。
可就是这么朴实无华且枯燥的一句话,把我给难住了。在这条消息回复里,我把所有能点的地方点了一遍,也没找到这个所谓的ticket是什么东西。

当我的鼠标都要点烂了时,终于在别的老哥的提示下找到了答案,是要点击这个issue中的这个毫不起眼的Respond按钮啊!

说实话,在没有人告诉我这是个按钮之前,我一直以为这玩意就是一个破标签…
在我们把这个issue的状态切换回Open后,过个几分钟,如果没有其他问题,那么你就会收到下一条回复:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Iaz0tfy-1673228105070)(https://files.mdnice.com/user/7589/b4fbe2e7-3b67-44b1-832f-7fddfbac8bdb.png)]
收到这条消息,就说明我们的groupId已经准备好可以使用了,并且之后可以用当前这个sonatype的账号发布snapshot和release版本的jar包到它的oss仓库中了。
接着看下面一段,根据构建配置,第一个组件可能会在成功部署(deploy)后自动发布(release)。如果发生这种情况,那么我们会收到一条消息,来确认我们的jar包被同步到了maven中央仓库。
既然人家都 congratulation 了,那咱们也开心点,到这里在sonatype上的操作就暂时告一段落了…

gpg秘钥
接下来,我们需要使用gpg生成秘钥,在后续包发布jar时会根据生成的秘钥进行校验,因为sonatype也需要对上传这一行为进行权健的校验,避免无意义或恶意上传文件的行为。
1、安装gpg
官网下载地址:
window版下载地址:
我在下载了window版的安装文件后,一路无脑点击下一步就可以完成安装了。
2、创建秘钥
在安装完成gpg后,在命令行下通过指令来生成一个秘钥:
gpg --gen-key
在生成的过程中,首先会要求输入姓名和邮箱地址,在命令行窗口下填完这两个信息后,还会弹窗要求输入一个密码:

这个密码非常重要,一定要记住,后面在项目deploy的时候还会用到。填完后继续,秘钥就会成功生成并保存在本地目录下了:

3、上传秘钥
在秘钥生成完后,我们需要把公钥上传到公共服务器供sonatype验证,可以通过下面的命令将公钥上传:
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys XXXXX
在公钥上传成功后,还可以通过--recv-keys来验证公钥:

虽然我这里一次就上传成功了,但是在看其他教程的过程中,也可能会出现失败的情况,这种情况可以尝试上传到其他的存放公钥的服务器:
- pool.sks-keyservers.ne
- keys.openpgp.org
- pgp.mit.edu
端口的话都是11371,这些公钥服务器间会同步它们的数据给其他服务器,所以只要上传成功到其中一台就行。
maven 设置
接下来需要修改本地maven的配置,为了保险起见,我建议大家最好同时修改.m2和conf目录下的配置文件,否则有可能出现一些奇怪的问题。
1、server
首先在配置文件中添加一个server节点,配置sonatype的用户名及密码:
<servers>
<server>
<id>ossrh</id>
<username>${sonatype username}</username>
<password>${sonatype password}</password>
</server>
</servers>
2、profile
接着添加一个profie节点,配置gpg信息,这里就需要填入在生成gpg秘钥过程中,我们在弹窗中输入的密码了:
<profiles>
<profile>
<id>ossrh</id>
<properties>
<gpg.executable>gpg</gpg.executable>
<gpg.passphrase>${弹窗输入的那个密码}</gpg.passphrase>
</properties>
</profile>
</profiles>
<activeProfiles>
<activeProfile>ossrh</activeProfile>
</activeProfiles>
在修改完成后,可以在命令行窗口下,通过命令查看我们修改过的配置是否已经生效了:
mvn help:effective-settings
如果显示的内容和配置文件中的一样,那么恭喜,后面就只还剩下亿点点工作了。

项目pom修改
在maven环境修改完成后,我们还需要对项目的pom文件进行一些修改。
1、基础信息
如果我们之前的代码中,groupId和sonatype上注册的不一致,那么需要修改项目的groupId改为一致。既然都要发布了,顺便也把version改为release版本吧。
<groupId>io.github.trunks2008</groupId>
<artifactId>ulquiorra-cache</artifactId>
<version>0.0.1-RELEASE</version>
2、distributionManagement
添加distributionManagement信息,声明要打包到sonatype的maven仓库中去。
<distributionManagement>
<snapshotRepository>
<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>
3、plugins
这里需要添加各种plugin插件,除了常用的maven-compiler和maven-deploy插件外,还需要下面几个关键插件:
nexus-staging-maven-plugin: sonatype插件,用来将项目发布到中央仓库使用maven-source-plugin:生成java source.jar文件maven-javadoc-plugin:生成java doc文档maven-gpg-plugin:对文件进行自动签名
使用到的全部插件详细配置如下,直接拷到项目中就可以使用:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- sonatype插件,发布使用-->
<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>
<!-- 生成java source.jar -->
<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>
<!-- 生成java doc文档 -->
<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>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 工程文件自动签名-->
<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>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
</plugins>
至于在idea中,插件经常下载失败报红线的问题,个人测试可以先把它们加到dependencies中拉取下来,成功率能高不少…

4、开源签名证书
添加license信息,使用Apache Licene 2.0 协议就行。
<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>
5、仓库信息
在这里填写一下项目的地址,把我们的github仓库地址贴上去就可以了。
<scm>
<url>
https://github.com/trunks2008/ulquiorra-cache
</url>
<connection>
scm:git@github.com/trunks2008/ulquiorra-cache.git
</connection>
<developerConnection>
scm:git@github.com/trunks2008/ulquiorra-cache.git
</developerConnection>
</scm>
6、开发人员信息
补充开发者的个人信息,虽然估计也没什么人会联系我就是了。
<developers>
<developer>
<name>hydra</name>
<email>765666922@qq.com</email>
<organization>https://github.com/trunks2008</organization>
<timezone>+8</timezone>
</developer>
</developers>
在添加完这么多茫茫的信息后,我的pom文件成功的从70行变成了200多行……

发布
到这里所有的基本工作就都做完了,下面执行激动人心的deploy命令!
mvn clean deploy -DskipTests
命令执行结果:

果然是都到最后一步了,还是不能掉以轻心啊…

查了一下这个报错,大概就是SSL的问题,修改一下deploy命令的参数就行~
mvn clean deploy -DskipTests
-Dmaven.wagon.http.ssl.insecure=true
-Dmaven.wagon.http.ssl.allowall=true
再次执行命令:

奇怪的错误又出现了…

这次的问题比较简单,就是项目中的pom中缺失了一些项目信息,修改pom文件,添加下面的信息:
<name>ulquiorra-cache</name>
<description>a tool about bilayer cache</description>
<url>https://github.com/trunks2008/ulquiorra-cache</url>
再次尝试deploy,终于成功了!

登录https://s01.oss.sonatype.org/,看一眼oss仓库,我们的jar包已经上传成功了。

你以为到这里就结束了?恰恰相反,更加漫长的等待才刚刚开始…

漫长的等待
在项目deploy成功后,回到sonatype,活动日志区很快就会收到一条新消息:

大意就是sonatype到中央仓库的同步是激活的,当我们成功发布组件后,通常30分钟左右就可以在 https://repo1.maven.org/maven2/上访问到了,但是更新到https://search.maven.org/可能需要4个小时。
按照这个提示,等半个小时再访问repo1.maven.org,经过一路搜索最后可以找到:

过四个小时再访问search.maven.org,果然在上面也可以查找到我的jar包了,sonatype诚不我欺…

讲道理的话,既然发布成功了,那我们就可以在项目中按照这个maven坐标拉取到jar包了,但是在项目中就是死活拉不下来…
于是我灵机一动,改为使用gradle:
dependencies {
implementation("io.github.trunks2008:ulquiorra-cache:0.0.1-RELEASE")
}
你别说,居然真的成功了…

不过话说回来,在日常工作中,我还是更习惯用https://mvnrepository.com来查找maven依赖,至于什么时候能在上面搜到,我实测了一下,这个周期真是长的可怕。
在14号就上传jar包成功后,直到17号才能在mvnrepository上查找到…

最后
那么,这次不那么顺利的踩坑之旅到这里就基本上结束了,总的来说,发布jar包到中央仓库真是个体力活。
在实际操作的过程中,有着数不完的坑,动不动一个点就可能卡住好几个小时,即便成功发布了,后续还有漫长的等待时间,总之就是非常心累…
对于那位在git上给我提issue的兄弟,我只有一句话想说…

本文在sonatype上提交的issue,以及提交的项目git地址我都放在下面了,大家如果有需求的话,可以参考一下~
sonatype的issue地址:https://issues.sonatype.org/browse/OSSRH-86180
项目的github地址:https://github.com/trunks2008/ulquiorra-cache
那么,这次的分享就到这里,我是Hydra,我们下篇再见。

作者简介,
码农参上,一个热爱分享的公众号,有趣、深入、直接,与你聊聊技术。欢迎添加好友,进一步交流。
发布了一个jar包到中央仓库,我的心好累…的更多相关文章
- 发布Jar包到中央仓库
参考流程 https://blog.csdn.net/qq_36838191/article/details/81027586 备份还原 gpg-keys https://blog.rathena.c ...
- Maven命令安装jar包到本地仓库
https://blog.csdn.net/moxiong3212/article/details/78767480 当需要的jar包在中央仓库找不到或者是想把自己生成的jar包放到的Maven仓库中 ...
- 如何发布自己的 jar 包到 maven 中央仓库(待更新...)
参考链接 如何发布自己的 jar 包到 maven 中央仓库
- 使用github作为maven仓库存放发布自己的jar包依赖 实现多个项目公共部分代码的集中,避免团队中多个项目之间代码的复制粘贴
使用github作为maven仓库存放发布自己的jar包依赖 实现多个项目公共部分代码的集中,避免团队中多个项目之间代码的复制粘贴. 1.首先在本地maven位置的配置文件setting.xml(没有 ...
- maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用
maven 引用另一个jar包 需要先打包在仓库里面 并在pom里面配置 才可以引用
- Maven系列(十)发布自己的项目到 Maven 中央仓库
Maven 发布自己的项目到 Maven 中央仓库 可能很多人都在用 Maven 仓库,但是如果要问怎么发布项目到中央仓库,估计很多人都不知道了,下面本篇文章带大家往中央仓库发布一个自己的 Maven ...
- maven无法下载依赖jar包—几种仓库的区别
一.问题背景 最近这两天,感觉自己智商急剧退化,到了自己都捉急的地步,呃,有必要记录下来,以后智商被人甩几条街的时候,看看这篇文字,找找灵感也是好的! 这个项目呢,是用IDEA开发的,我一切都弄好了, ...
- maven命令学习-发布上传jar包-deploy
Maven学习六之利用mvn deploy命令上传包 转http://blog.csdn.net/woshixuye/article/details/8133050 mvn:deploy在整合或者发布 ...
- Maven手工安装jar包到本地仓库
使用maven,少不了的就是要被"包下载失败"这种问题折腾. jar包下载失败后.我们选择手工把jar下载下来.(能够下载到指定jar的途经非常多) 以下随便找了一个jar包为例. ...
- 多个module实体类集合打一个jar包并上传至远程库
本章内容主要分享多个module中的实体类集合生成到一个jar包中,并且发布到远程库:这里采用maven-assembly-plugin插件的功能来操作打包,内容不长却贴近实战切值得拥有,主要节点内容 ...
随机推荐
- Pytest进阶使用
fixture 特点: 命令灵活:对于setup,teardown可以省略 数据共享:在conftest.py配置里写方法可以实现数据共享,不需要import导入,可以跨文件共享 scope的层次及神 ...
- RMarkdown进阶操作
技术背景 Markdown大家都比较熟悉了,特别是在写程序文档和写数学公式时,拥有着无与伦比的便利性.同时在前面的一篇博客中我们介绍了使用RMarkdown去写Latex Beamer演示文档的方法, ...
- Vue学习之--------组件自定义事件(绑定、解绑)(2022/8/21)
文章目录 1.基础知识 2.代码实例 2.1 App.vue 2.2 school.vue 2.3 student.vue 3.测试效果(略) 4.实际应用(在组件化编码实战三的基础上改进) 4.1 ...
- servlet过滤器--使用过滤器统计网站访问人数的计数(注解形式)
文章目录 1.什么是过滤器? 2.过滤器核心对象 3.过滤器创建和配置 4.举例子 1.什么是过滤器? 主要用于对客户端的请求进行过滤处理,再将经过过滤后的请求转交给下一个资源. 2.过滤器核心对象 ...
- 知识图谱-生物信息学-医学顶刊论文(Briefings in Bioinformatics-2021):生物信息学中的图表示学习:趋势、方法和应用
4.(2021.6.24)Briefings-生物信息学中的图表示学习:趋势.方法和应用 论文标题: Graph representation learning in bioinformatics: ...
- nrf52——DFU升级USB/UART升级方式详解(基于SDK开发例程)
摘要:在前面的nrf52--DFU升级OTA升级方式详解(基于SDK开发例程)一文中我测试了基于蓝牙的OTA,本文将开始基于UART和USB(USB_CDC_)进行升级测试. 整体升级流程: 整个过程 ...
- Go语言核心36讲42-----io包中接口的好处与优势
我们在前几篇文章中,主要讨论了strings.Builder.strings.Reader和bytes.Buffer这三个数据类型. 知识回顾 还记得吗?当时我还问过你"它们都实现了哪些接口 ...
- django启动报错:DisallowedHost at /
学习django第一天,第一次启动服务就报错,报错内容如下: DisallowedHost at / Invalid HTTP_HOST header: '192.168.116.22:8000'. ...
- c++ const和指针
const int *p: 定义指针,指向的变量的值不能修改(指向整型常量或普通整型,但值不能通过指针修改) int const *p: 同上 int * const p=&a: 一直指向a, ...
- Base64 学习
base64是什么 Base64,就是包括小写字母a-z,大写字母A-Z,数字0-9,符号"+" "/ "一共64个字符的字符集,(另加一个"=&qu ...