如何将开源项目发布到 maven
中央仓库,让别人通过依赖使用你的开源项目,想必很多朋友都有过这个想法。
去年我就想将自己开源的一个 miniexcel
工具包发布到 maven
仓库,在项目中通过依赖导入使用,但那时候感觉太麻烦了,然后看到有文章介绍说可以使用 jitpack
,这个就非常简单了。但是最近在项目中,由于是使用 maven
,配置 jitpack
总是导入不了依赖,一直报错,为了不拖慢进度,我还是放弃了使用这个工具。
因此,我还是想将项目打包发布到 maven
中央仓库。折腾了一天,踩了很多坑才成功的。希望本篇对大家有所帮助。
项目构建工具: Gradle
,版本: 6.2.2
,官方文档当前最新版本。原本是使用 gradle4.5.1
版本的,但是找不到 4.5
版本的 MavenPublication
的文档,倒不如直接将 Gradle
切换到 6.2.2
版本。关于 MavenPublication
看到后面你就知道了。
首先是到 https://issues.sonatype.org/
注册账号,注册成功后登陆。需要注意的一点是,账号的密码必须要包含大写字母、小写字母、数字加特殊符号。登陆成功后,首次登陆会让你选择语言,可以选择中文,非常友好。
如果选择的是中文,那么下一步就是在首页点击“新建”,可以理解为工单,或者英文叫 issue
,或者可以理解为新建项目。在弹出窗口填写 issue
信息。
项目选择 Community Support - Open Source Project Repository Hosting
,问题类型选择 New Project
。概要随便填,描述写项目的介绍。最后就是填写 Group Id
、项目地址、 git
仓库地址。
这里 Group Id
我使用我的 gitbub
的地址。如果是填写你自己的域名,是需要验证的,如 com.wujiuye
,那么后面需要证明这个域名是你的,怎么证明后面提到。填写 github
的域名也是需要验证的,下一步介绍。
填写完之后点击右下角的新建按钮即可创建项目。
在项目创建成功后,你注册时填写的邮箱会收到一封邮件,你可以通过查看邮件看下一步要做说明,或者你也可以直接在项目详情页的底部“注释”栏看评论,此时会有一个评论,与邮件收到的内容是一样的。意思是需要你在你的 github
上创建一个名为 OSSRH-56052
的项目。
如果你在创建项目时,填写的 Group Id
是你自己的域名,这时就会要求你配置 DNS
来验证这个域名是你的,或者其它方式,这个我没去试,具体怎么验证我也不清楚。
在你的 github
上创建完项目之后,还需要回到 sonatype
网站的项目详情页面,在“注释”下面回复说你已经完成这一步了。
稍等一会之后,你会收到它的新回复。
意思是现在你可以将 SNAPSHOT
、 RELEASE
的构件( jar
)部署到仓库 xxx
了。现在回到你的项目,在 build.gradle
配置文件下,添加配置,使用 maven-publish
插件将项目打包发布到仓库。
这里参考了 gradle
官方文档给的配置: https://docs.gradle.org/current/javadoc/org/gradle/api/publish/maven/MavenPublication.html
先添加 maven-publish
插件
plugins { id 'java' // maven 发布插件 id 'maven-publish' } 复制代码
将 group
改为你在 sonatype
创建的项目的 Group Id
。我们先简单配置看下是否能够发布成功,所以先发布一个 SNAPSHOT
版本,需要在版本名后面加上 -SNAPSHOT
,否则发布到 SNAPSHOT
仓库会失败。
group 'com.github.wujiuye' version '1.0.0-SNAPSHOT' 复制代码
注意,以 -SNAPSHOT
结尾的版本号发布到 release
仓库会失败,只能发到 snapshot
仓库,所以后面发布 release
版本时,需要去掉 -SNAPSHOT
。
接着是 publishing
的配置。
publishing { publications { // 推送配置 publishMyProjectMiniexcel(MavenPublication) { // 编译jar包 from components.java // 打包源码 artifact sourcesJar } } // 到 https://oss.sonatype.org/#nexus-search; 搜索是否上传成功 repositories { } } 复制代码
repositories
详细配置如图:
详细的 build.gradle
后文会给出。这里配置两个仓库,一个是 Release
仓库,一个是 Snapshot
,名称 name
是自己随便填的, url
就是上一步在 sonatype
你的项目详情页收到的回复的两个地址。 credentials
配置的是你登陆 sonatype
的账号和密码。在你项目的 build.gradle
同级目录下,新建一个 gradle.properties
文件,将账号密码写在这个配置文件中。
注意,不要把这个文件提交到 github
,不然你密码就泄漏了。最好是在你安装的 gradle
的全局 gradle.properties
文件中配置,这也是推荐的做法。
如何做到安全(这一步可以先忽略,等后面测试发布成功了,再回来完成这个步骤):
GRADLE_USER_HOME
目录下的 gradle.properties
文件中; gradle.properties
中相同的变量则会覆盖 GRADLE_USER_HOME/gradle.properties
中的配置。在执行 build
的时候,用户名和密码会被读取,如果不存在的话会报错,比如别人下载了你的源码调试,将不能构建成功,所以项目目录下的 gradle.properties
中保留用户名和密码并且是错误的用户名和密码; gradle.properties
的用户名和密码配置。让构建的时候获取 GRADLE_USER_HOME/gradle.properties
中的配置,构建完成后,再还原回来,防止别人构建失败。 现在就可以在 idea
中点击右侧的 gradle
,也就是前面一张图的红色箭头指向(配置仓库的那张)。在任务下的 publishing
选择 publish+你配置的推送任务名称+PublicationToSnapshotRepository
任务执行。
推送成功后到 https://oss.sonatype.org/#nexus-search
搜索,看看是不是发布成功了。
现在我们需要完善配置,发布 Release
版本到 Release
仓库。我们先只是修改下版本后,去掉 -SNAPSHOT
,然后执行 publish+你配置的推送任务名称+PublicationToReleaseRepository
任务。注意,与发布快照版本不是同一个任务,仔细看区别。
然后到 https://oss.sonatype.org/#stagingRepositories
查看发布好的构件。点击左侧的 Staging Repositories
,第一个就是刚刚发布的 jar
,此时的构件状态为 Open
。
选中构件,并点击上方的 Close
,然后会提示你是否确认,继续点击 Confirm
。
点击 Refresh
,在下边的 Activity
选项卡中查看状态。不出意外,是不会成功的!因为这才是填坑的开始。
上图中,当前这次 close
的状态,有很多项是验证失败的,就是图标打个叉叉的。
失败的选项有:
POM
验证失败,原因是没有配置 POM
信息 Javadoc
验证失败,原因是没有上传 Javadoc
Signature
签名验证失败,这个就比较复杂了。 我们先解决 pom
和 javadoc
验证失败的问题。回到项目中,在 build.gradle
文件完善配置,如下:
plugins { id 'java' // maven 发布插件 id 'maven-publish' } group 'com.github.wujiuye' version '1.1.0-RELEASE' repositories { mavenCentral() } dependencies { // excel表格 compile group: 'org.apache.poi', name: 'poi', version: '3.17' compile group: 'org.apache.poi', name: 'poi-ooxml', version: '3.17' compile group: 'org.apache.poi', name: 'poi-ooxml-schemas', version: '3.17' testCompile group: 'junit', name: 'junit', version: '4.12' } // 打包源码 task sourcesJar(type: Jar) { classifier = 'sources' from sourceSets.main.allJava } // 生成 javadoc jar task javadocJar(type: Jar) { classifier = 'javadoc' from javadoc.destinationDir } publishing { publications { // 推送 publishMyProjectMiniexcel(MavenPublication) { // 编译jar包 from components.java // 打包源码 artifact sourcesJar // javadoc artifact javadocJar pom { name = "miniexcel" description = "基于poi封装的一套excel文件读写工具,完美解决oom问题。优雅的使用设计模式提供更简单的使用姿势!更有详细的使用教程。如需获取帮助,关注微信公众号:Java艺术" url = "https://github.com/wujiuye/miniexcel" licenses { license { name = "The Apache License, Version 2.0" url = "http://www.apache.org/licenses/LICENSE-2.0.txt" } } developers { developer { id = "wujiuye" name = "wujiuye" email = "419611821@qq.com" } } scm { connection = "scm:git:https://github.com/wujiuye/miniexcel.git" developerConnection = "scm:git:https://github.com/wujiuye/miniexcel.git" url = "https://github.com/wujiuye/miniexcel" } } } } // 到 https://oss.sonatype.org/#nexus-search; 搜索是否上传成功 repositories { // 发布Release版本可在版本号后面带上'-RELEASE',也可不带 maven { name 'Release' url 'https://oss.sonatype.org/service/local/staging/deploy/maven2' credentials { username = "${NEXUS_USERNAME}" password = "${NEXUS_PASSWORD}" } } // 发布Snapshot快照版本必须在版本号后面加上'-SNAPSHOT' maven { name = 'Snapshot' url = 'https://oss.sonatype.org/content/repositories/snapshots' credentials { username = "${NEXUS_USERNAME}" password = "${NEXUS_PASSWORD}" } } } } 复制代码
现在重新执行一遍 publish+你配置的推送任务名称+PublicationToReleaseRepository
任务,再回到 https://oss.sonatype.org/#stagingRepositories
。由于前面有提交过,现在刷新会有两个构件,看最后一个,或者看时间,选择最新上传的那个构件,继续完成 Close
步骤。
这次已经少了两个错误了,只剩一个签名验证失败。而这个相对来说比较复杂。
我们需要使用 gpg
生成密钥,以我的电脑为例, mac
下安装 gpg
非常简单,使用 brew
安装就可以了。 windows
下更容易了,一大堆教程, mac
下的教程还比较难找。
brew install gpg 复制代码
使用 gpg --gen-key
命令生成密钥。
MacBook-Pro:~ wjy$ gpg --gen-key gpg (GnuPG) 2.2.19; Copyright (C) 2019 Free Software Foundation, Inc. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. 注意:使用 “gpg --full-generate-key” 以获得一个功能完整的密钥产生对话框。 GnuPG 需要构建用户标识以辨认您的密钥。 真实姓名: wujiuye 电子邮件地址: 419611821@qq.com ..... 复制代码
填完电子邮箱后会要求输入密钥的密码。
在创建完成后,可以使用 gpg --list-keys
命令查看。
MacBook-Pro:~ wjy$ gpg --list-keys gpg: 正在检查信任度数据库 gpg: marginals needed: 3 completes needed: 1 trust model: pgp gpg: 深度:0 有效性: 1 已签名: 0 信任度:0-,0q,0n,0m,0f,1u gpg: 下次信任度数据库检查将于 2022-03-23 进行 /Users/wjy/.gnupg/pubring.kbx ----------------------------- pub rsa2048 2020-03-23 [SC] [有效至:2022-03-23] 5FE36BC89979FABF8D48ADD0B6559088974BA646 uid [ 绝对 ] wujiuye <419611821@qq.com> sub rsa2048 2020-03-23 [E] [有效至:2022-03-23] 复制代码
在 build.gradle
配置文件添加签名插件。
plugins { id 'java' // maven 发布插件 id 'maven-publish' // 签名插件 id 'signing' } ....... publishing { ....... } // 必须在 publishing 配置之后 signing { sign publishing.publications.publishMyProjectMiniexcel } 复制代码
然后在 gradle.properties
文件中添加密钥项的配置。
### gpg --list-keys --keyid-format short 查出来的 signing.keyId=52FEDB1A ### 创建密钥时的密码 signing.password=wujiuye950605 ### .gpg文件的路径 signing.secretKeyRingFile=/Users/wjy/.gnupg/secring.gpg 复制代码
使用 gpg --gen-key
命令创建密钥并没有生成 secring.gpg
文件,现在我们可以通过命令 gpg --export-secret-keys
生成 secring.gpg
,生成的 secring.gpg
文件的路径便是 gradle.properties
配置文件中 signing.secretKeyRingFile
这项的值。
gpg --export-secret-keys -o /Users/wjy/.gnupg/secring.gpg 复制代码
还有一个 signing.keyId
可以通过 gpg --list-keys --keyid-format short
查询出来。
注意,是红框中的那个。现在重新执行一遍 publish+你配置的推送任务名称+PublicationToReleaseRepository
任务,再回到 https://oss.sonatype.org/#stagingRepositories
。可以继续完成 Close
步骤了。
如果签名还是验证失败,失败信息如下:
failureMessage No public key: Key with id: (4e999e3952fedb1a) was not able to be located on <a href="http://keyserver.ubuntu.com:11371/">http://keyserver.ubuntu.com:11371/</a>. Upload your public key and try the operation again. failureMessage No public key: Key with id: (4e999e3952fedb1a) was not able to be located on <a href="http://keys.openpgp.org:11371/">http://keys.openpgp.org:11371/</a>. Upload your public key and try the operation again. failureMessage No public key: Key with id: (4e999e3952fedb1a) was not able to be located on <a href="http://pool.sks-keyservers.net:11371/">http://pool.sks-keyservers.net:11371/</a>. Upload your public key and try the operation again. 复制代码
说明我们还需要将密钥发送到 keyserver.ubuntu.com:11371
、 keys.openpgp.org:11371
、 pool.sks-keyservers.net:11371
这几个地址中的其中一个,按照验证顺序,首选第一个。
MacBook-Pro:.gnupg wjy$ gpg --keyserver http://keyserver.ubuntu.com:11371 --send-keys 5FE36BC89979FABF8D48ADD0B6559088974BA646 gpg: 正在发送密钥 B6559088974BA646 到 http://keyserver.ubuntu.com:11371 复制代码
现在重试 Close
就能够成功了。
耐心等待邮件吧,这个过程是需要很久的。我大概等了一个小时,才收到邮件。
邮件中提示说,我还需要选中最后一次 Close
成功的构件,点击 Release
按钮。继续返回 https://oss.sonatype.org/#stagingRepositories
。
现在 Release
按钮已经变成可点击了,愉快的点击发布吧。大概过了二十多分钟,收到一封邮件。此时已经凌晨一点半了。
意思是说,再过十分钟,就可以在 maven
中央仓库中搜索到了,不过对于 https://search.maven.org
这个网站可能还要两个小时才能搜索到。
成果:
https://search.maven.org/search?q=miniexcel 复制代码
最后不要忘记了在 sonatype
上的项目详情页回复下已经完成,当然不是必须的。以后想发布开源项目到 maven
,只要 Group Id
不变,就可以省略很多步骤了。
参考资料:
【如何将自己的开源项目发布到Maven中央仓库】 https://blog.csdn.net/sinat_23290725/article/details/85018092 【Gradle 发布 JAR 包到 maven 中央仓库(sonatype )】 https://blog.csdn.net/mr_zhuqiang/article/details/84564256 【gradle签名插件配置问题】 https://stackoverflow.com/questions/27936119/gradle-uploadarchives-task-unable-to-read-secret-key 【MavenPublication配置参考】 https://docs.gradle.org/current/javadoc/org/gradle/api/publish/maven/MavenPublication.html 复制代码