MavenCentral 是一个权威的代码中央仓库,JCenter 相当于一个公共的存储空间,不过 JCenter 早就被标记为废弃,而自 2021 年 3 月 31 日后,JCenter 也不再接受任何提交。所以 MavenCentral 和搭建自己的私人服务器就变成了唯二的选择,不过很明显前者的技术难度和维护成本更低,本文将详细介绍如何向 MavenCentral 上传自己的项目。

本文中提到的所有有关账户、密码、密钥的信息均不要上传到网上!!!
本文中提到的所有有关账户、密码、密钥的信息均不要上传到网上!!!
本文中提到的所有有关账户、密码、密钥的信息均不要上传到网上!!!

Sonatype

  首先我们需要在 Sonatype 上创建一个工单,再次之前,我们需要拥有一个 Sonatype 账户。

注册

  如果你已经有 Sonatype 账户了的话,可以直接跳过本小结。

  我们可以在这个地方注册账户,打开页面后,在网页中的栏目中填写相应内容即可:

  • Email - 邮箱地址,请务必填写有效的邮箱地址
  • Full Name - 网名,随意填写
  • Username - 用户名,登陆时使用的名称
  • Password - 密码
  • 最后一个空是填写验证码

  全部填写完成后,就可以点击Sing up注册账户了,如果填写的信息不符合要求,则会通过红色的文字进行提示,按照提示进行更改即可。

  下一个页面会让你选择语言,选择任何语言均可,这里我选择了中文。

创建工单

  接下来就需要创建工单了,点击上方菜单中的“新建”按钮,然后在弹出的窗体中填写相应信息:

  其余项保持默认即可,如果需要修改按输入框下方的提示修改即可。

  这里我们详细说明一下Group Id,这个包路径并不是指你的项目中使用的包路径,而是你想要将包发布到哪一个 id 下。

  如果你有自己的域名的话可以直接写自己的域名(可以加二级域名,域名倒序填写),比如我填写的是top.kmar.game。如果没有自己的域名那就填 Github 之类的代码仓库的个人地址,格式为:io.github.yourname

  关于Group Id的更多信息可以参考官方文档

  信息填写完备后就可以点击创建按钮了。

  等官方人员审核你的工单后,他们会在你的工单下发布一个评论并修改你的工单状态(工单状态在页面顶部)。

  我收到的评论内容如下:

To register this Group Id you must prove ownership of the domain kmar.top. Please complete the following steps to continue:

  1. Add a DNS TXT record to your domain with the text: OSSRH-90691. Please read https://central.sonatype.org/faq/how-to-set-txt-record/
  2. Edit this ticket and set Status to Open.

More info: https://central.sonatype.org/publish/


If you do not own this domain, you may also choose a different Group Id that reflects your project hosting. io.github.emptydreams would be valid based on your Project URL.

To continue the registration process, please follow these steps:

  1. Create a temporary, public repository called https://github.com/emptydreams/OSSRH-90691 to verify github account ownership.
  2. Edit this ticket, update the Group ID field with the new GroupId, and set Status to Open.

More info: https://central.sonatype.org/publish/requirements/coordinates/

  评论的大致意思就是需要验证我们对填写的Group Id的所有权,避免私自占用他人的域。

  如果你是使用自己的域名,那么就在 DNS 解析记录中添加一条这样的记录:

1
2
3
记录类型:TXT
记录值:[留空(@)]
记录值:[官方让你填写的 TEXT](我的是:OSSRH-90691)

  如果你是使用的 Github,那就创建一个仓库,仓库名是官方给你的评论中的 URL 中提到的名称,比如说我的就是OSSRH-90691

  操作完毕后将工单状态修改为Open即可,不需要回复官方的评论,工单状态在页面顶部。

  官方审核完毕后会发评论通知,如果没有通过审核,按照回复修正后重新Open工单即可。

  我收到的回复大致内容如下:

Congratulations! Welcome to the Central Repository!

top.kmar.game has been prepared, now user(s) Kmar can:

Publish snapshot and release artifacts to s01.oss.sonatype.org

Have a look at this section of our official guide for deployment instructions:

https://central.sonatype.org/publish/publish-guide/#deployment

  注意上述回复中加粗的域名,这个是我们上传的仓库的地址,如果你收到的回复和我的不一样,以你收到的回复为准。

GPG 密钥

  我们需要使用第三方工具生成 GPG 密钥并上传到服务器,Windows 平台推荐使用Gpg4win,其它平台可以参考网络上的其它教程。

  下载 Gpg4win 并安装后运行,点击“创建个人密钥对”,按照下图内容填写信息:

配置示例

  其中“使用密码句保护生成的密钥”必须勾选,有效期取消,密钥类型可以随意选择,名字和电子邮件地址填写你自己的,其它保持默认即可。

  然后点击OK后在弹出的窗体中填写并重复密码即可完成密钥的创建,创建完毕后会弹出一个窗口,上面写的十六进制字符串就是你的指纹,我们需要保存这个值(没记录也没关系,双击你的证书也可以查看指纹)。

  证书创建完毕后邮件创建的证书,选择“在服务器上发布”,上传过程中没有进度条,耐心等待即可,如果报错说上传失败重试即可。成功后可以点击“在服务器上查找”,在里面搜索你的证书确认是否上传成功。

  然后打开命令提示符,执行以下指令:

1
gpg --export-secret-keys [密钥指纹] > [导出路径,例如:secret.gpg]

  然后将生成的 gpg 文件移动到项目根目录下的某一个目录中(这个文件不要上传到网上!!!),这样,GPG 密钥就创建完了。

Gradle 配置

  接下来我们需要配置 gradle 的相关内容,在gradle.properties中添加如下信息:

   警告:不要将该文件上传到网上,会暴露你的用户密码!!!

1
2
3
4
5
6
ossrhUsername=[Sonatype 用户名]
ossrhPassword=[Sonatype 密码]

signing.keyId=[上面提到的指纹的后 8 位]
signing.password=[设置的密码]
signing.secretKeyRingFile=[证书相对路径(相对于项目根目录),例如:public/secret.gpg]

  然后参照如下代码修改你的gradle.build

如果你的项目是使用 Java 编写的,可以参考下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
plugins {
id 'maven-publish'
id 'signing'
}

group = '......' // 必须和你填写的 Group Id 保持一致
archivesBaseName = 'cg-engine' // 项目的 ID,必须符合后面的要求:仅包含英文小写字母、阿拉伯数字、下划线、分割线且以英文字母开头
version = '1.0-SNAPSHOT' // 项目版本号,开发版以“-SNAPSHOT”结尾,非开发版直接使用数字和小数点

java {
withSourcesJar()
withJavadocJar()
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifactId archivesBaseName

pom {
name = 'Console Game Engine' // 项目名称
description = 'A console game engine for the JVM.' // 项目简介
url = 'https://github.com/EmptyDreams/ConsoleGameEngine' // 项目主页

scm { // 版本控制的相关信息,参考我填写的内容
url = 'https://github.com/EmptyDreams/ConsoleGameEngine'
connection = 'scm:git:git:github.com/EmptyDreams/ConsoleGameEngine.git'
developerConnection = 'scm:git:ssh://git@github.com:EmptyDreams/ConsoleGameEngine.git'
}

licenses {
license {
name = 'The Affero General Public License, Version 3.0' // 协议名称
url = 'https://www.gnu.org/licenses/agpl-3.0.en.html' // 协议官网
}
}

developers {
developer {
id = 'Kmar' // 作者 id
name = '空梦' // 作者名称
email = 'minedreams@qq.com' // 作者邮箱
}
}
}
}
}

repositories {
maven {
name = archivesBaseName

// 如果 Sonatype 官方人员给你发的域名不是 s01.oss.sonatype,请把域名替换成官方人员告知你的域名
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl

credentials {
username ossrhUsername
password ossrhPassword
}
}
}
}

signing {
sign publishing.publications.mavenJava
}

如果你的项目是使用 Kotlin 编写的,可以参考下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
plugins {
id 'org.jetbrains.kotlin.jvm' version 'x.x.x'
id 'org.jetbrains.dokka' version 'x.x.x'
id 'maven-publish'
id 'signing'
}

group = 'top.kmar.game'
archivesBaseName = 'cg-engine'
version = '1.2.0'

java {
withSourcesJar()
}

dokkaHtml {
outputDirectory.set(file("build/documentation/html"))
}

tasks.register('dokkaJavadocJar', Jar.class) {
dependsOn(dokkaHtml)
from(dokkaHtml)
archiveClassifier.set("javadoc")
}

publishing {
publications {
mavenJava(MavenPublication) {
from components.java
artifact(tasks["dokkaJavadocJar"])
artifactId archivesBaseName

pom {
name = 'Console Game Engine' // 项目名称
description = 'A console game engine for the JVM.' // 项目描述
url = 'https://github.com/EmptyDreams/ConsoleGameEngine' // 项目主页

scm { // 版本控制的相关信息,参考我填写的内容
url = 'https://github.com/EmptyDreams/ConsoleGameEngine'
connection = 'scm:git:git:github.com/EmptyDreams/ConsoleGameEngine.git'
developerConnection = 'scm:git:ssh://git@github.com:EmptyDreams/ConsoleGameEngine.git'
}

licenses {
license {
name = 'The Affero General Public License, Version 3.0' // 协议名称
url = 'https://www.gnu.org/licenses/agpl-3.0.en.html' // 协议官网
}
}

developers {
developer {
id = 'Kmar' // 作者 id
name = '空梦' // 作者名称
email = 'minedreams@qq.com' // 作者邮箱
}
}
}
}
}

repositories {
maven {
name = archivesBaseName

// 如果 Sonatype 官方人员给你发的域名不是 s01.oss.sonatype,请把域名替换成官方人员告知你的域名
def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/"
url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl

credentials {
username ossrhUsername
password ossrhPassword
}
}
}
}

signing {
sign publishing.publications.mavenJava
}

  接下来同步一下 Gradle 即可。

发布

  上述步骤都完成后执行 Gradle 指令就可以将项目发布到网上了,publish指令是发布跨平台项目,publishJvmPublicationToMavenRepository指令是发布 JVM 部分。

  指令运行成功后(如果因为网络原因失败可以多试几次,可以不挂梯子)我们还需要登录 Nexus,Nexus 的网址就是上面 Sonatype 官方任意告诉你的域名,比如说我的是:https://s01.oss.sonatype.org/(这个网站不挂梯子也是可以使用的,如果一直访问错误可以尝试挂梯子)。

  进入网站后点击右上角的Login按钮登录,然后点击左侧列表中的Staging Repositories,接下来在中央的区域中点击Refresh按钮,然后你就会看到列表中出现了一个卡片,这个卡片就是你刚刚上传到服务器的项目。

  选中这个卡片,再点击菜单中的Close,描述随意填写即可,然后等待 Sonatype 给你发邮件,收到邮件后再次点击Refresh按钮,选中卡片,点击下方的Activity选项卡即可查看审核信息,如果有审核条目没有通过的话按照要求进行修改即可。

  所有审核条目都通过了的话,菜单中的Release按钮就是可点击的状态,点击Release,描述随意即可。

  如果你是第一次发布软件包,过一会 Sonatype 官方人员会在你的工单下面发布评论,通知你发布成功,等待缓存刷新即可。

  这时候,你就可以在项目依赖管理工具中通过 MavenCentral 加载你的项目了。


创作不易,扫描下方打赏二维码支持一下吧ヾ(≧▽≦*)o