保姆级教程:从 0 到 1 将项目发布到 Maven 中央仓库【2024年5月】

news2024/11/27 17:50:38

前言

大家好,我叫阿杆,不叫阿轩

最近写了一个参数校验组件,名字叫 spel-validator,是基于 javax.validation 的一个扩展,目的是简化参数校验。

我把项目开源到了GitHub https://github.com/stick-i/spel-validator ,但为了便于开发者使用,我决定将其发布到Maven中央仓库。

本文记录了我将项目发布到Maven中央仓库的完整过程,发布时间为 2024年5月5日,希望对你有所帮助。

2024 年 3 月 12 日起,官方调整了Maven包的发布方式,以前的老教程可能有些不适用了,如果你有发布 jar 包的需求,参考我这篇文章基本不会有什么问题。

官方通知

大致操作步骤如下:

  1. 配置sonatype账号
    1. 注册账号
    2. 创建命名空间
    3. 获取 User Token
  2. 配置GPG
    1. 安装GPG
    2. 生成密钥
    3. 发送公钥
  3. 配置pom文件
  4. 发布项目

配置sonatype账号

注册账号

进入官网:https://central.sonatype.com/

点击右上角 Sign In,然后点击下面的 Sign up,填写账号、密码、邮箱,注册自己的账号。

注册sonatype账号

创建命名空间

登录自己的账号之后,进入网站主页,点击右上角的 Publish 按钮,进入 Namespace 模块,然后点击 Add Namespace 按钮。

命名空间具有唯一性,必须是属于你且没有被其他人使用的,这里我使用了我的域名 cn.sticki 作为命名空间。

命名空间对应着 Maven 依赖的 groupId。

如果你直接通过GitHub注册的sonatype,应该会直接给你授权你账号的github命名空间。

如果你的命名空间注册失败,那可能是被其他人注册了,但官网上没看到写解决方案,如果你遇到了这种情况,可以网上搜一下解决方案。

sonatype-新建命名空间

点击提交后,需要验证命名空间。

验证域名

个人域名是通过 TXT 记录验证的,需要在域名的 DNS 解析中添加一条 TXT 记录。

添加域名解析记录

如果你没有域名,也可以使用 GitHub 或者 GitLab、Gitee 的用户名作为命名空间:

  • GitHub io.github.username
  • GitLab io.gitlab.username
  • Gitee io.gitee.username

比如我使用 GitHub 来作为我的命名空间,我的 GitHub 用户名是 stick-i,那么命名空间就写 io.github.stick-i

验证GitHub账号

GitHub的验证方式是通过让你新建仓库来验证的,你只需要根据它指定的名称新建一个仓库就好了。

配置好验证所需要的条件后,点击 confirm 按钮,然后等待验证通过,一般几秒钟就可以了。

获取 User Token

点击右上角的view account -> 点击Generate User Token -> 点击ok。

sonatype-生成UserToken

然后会得到一个这样的数据:

<server>
	<id>${server}</id>
	<username>xxxxxxx</username>
	<password>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx</password>
</server>

这个是你上传jar包时,用来验证你的身份的,不要泄露给别人。

把这段数据复制下来,粘贴到 Maven 的 setting.xml 里面,把 ${server} 改成你自定义的内容,这个自定义的内容要记下来,后面还要用到的,这里我改成了 sonatype-sticki

setting.xml

到这里 sonatype 账号就配置完毕了!

配置GPG

发布到Maven仓库中的所有文件都要使用GPG签名,以保障完整性。因此,我们需要在本地安装并配置GPG。

安装GPG

进入官网:https://gnupg.org/download/index.html

下载自己需要的版本,windows的同学跟我的操作一样进行下载就好了:

下载GPG

下载完直接安装,无脑下一步就好了,除了最后的文件路径要修改一下,前面的都不用管。

组件选择默认的就可以了,咱也没那么多需求,能用就行😋。

安装完之后,windows版会自动帮我们添加系统环境变量,我们随便找个地方打开cmd窗口就可以使用了(uTools的cmd除外)。

如果用不了的话,找到GPG的安装目录,目录的旁边还有一个 GnuPG 文件夹,然后进入 GnuPG 文件夹下的bin目录,在这些目录下打开 cmd 窗口。

我的bin目录

可以使用 gpg --version 来验证是否安装成功。

生成密钥

命令行输入gpg --gen-key

然后根据提示依次输入 Real name 和 Email address,注意这里的 Real name 必须填你在 sonatype 创建的 namespace。

如果你的namespace是用的自己的域名,那 name 就填域名,如果namespace是github的账号,那 name 就填GitHub账号名称,比如:

  • namespace:cn.sticki,Real name:cn.sticki
  • namespace:io.github.sticki,Real name:sticki

然后会弹出窗口让你输入密钥,这个密钥也需要记住,你每次上传的时候都会让你输入密码的。

接着我们再回到刚刚的cmd界面,注意最下面的信息,里面有一个公钥:

public and secret key created and signed.

pub   ed25519 2024-05-04 [SC] [expires: 2027-05-04]
      D8F859ACBB78E66AB97AB672766C17B3A2AA7414
uid                      cn.sticki <sticki@126.com>
sub   cv25519 2024-05-04 [E] [expires: 2027-05-04]

中间 D8F859ACBB78E66AB97AB672766C17B3A2AA7414 这段就是你的公钥,私钥它已经作为文件保存到你的电脑里了。

如果你不小心把cmd窗口关掉了,也可以通过 gpg --list-keys 命令来重新查看你以前生成过的密钥信息。

发送公钥

秘钥对生成好后,需要把公钥上传到公共服务器供sonatype验证:

gpg --keyserver keyserver.ubuntu.com --send-keys D8F859ACBB78E66AB97AB672766C17B3A2AA7414

中央服务器当前支持的 GPG 密钥服务器有:

  • keyserver.ubuntu.com
  • keys.openpgp.org
  • pgp.mit.edu

发送完需要验证是否成功:

gpg --keyserver keyserver.ubuntu.com --recv-keys D8F859ACBB78E66AB97AB672766C17B3A2AA7414

如果发送失败,可以多试几次,也可以换另外两个网址试试。

参考我的发送和验证过程:

发送公钥

到这里 GPG 就配置完毕了!

配置pom文件

这个部分略微有点麻烦,我直接放上我的完整pom文件给你参考,你再根据我在后面写的说明进行修改和调整就可以了。

<?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>cn.sticki</groupId>
	<artifactId>spel-validator</artifactId>
	<version>0.0.2-beta</version>
	<packaging>jar</packaging>
	<name>Spel Validator</name>
	<url>https://github.com/stick-i/spel-validator</url>

	<description>
		Bean Validator With Spring Expression Language
	</description>

	<developers>
		<developer>
			<id>sticki</id>
			<name>阿杆</name>
			<roles>
				<role>Project Manager</role>
				<role>Developer</role>
			</roles>
			<email>sticki@xxx.com</email>
			<url>https://github.com/stick-i</url>
		</developer>
	</developers>

	<issueManagement>
		<system>GitHub</system>
		<url>https://github.com/stick-i/spel-validator/issues</url>
	</issueManagement>

	<inceptionYear>2024</inceptionYear>

	<licenses>
		<license>
			<name>Apache License 2.0</name>
			<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
		</license>
	</licenses>

	<scm>
		<connection>scm:git:git://github.com/stick-i/spel-validator.git</connection>
		<developerConnection>scm:git:git@github.com:stick-i/spel-validator.git</developerConnection>
		<url>https://github.com/stick-i/spel-validator</url>
		<tag>HEAD</tag>
	</scm>

	<properties>
		<maven.compiler.source>8</maven.compiler.source>
		<maven.compiler.target>8</maven.compiler.target>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.hibernate.validator</groupId>
			<artifactId>hibernate-validator</artifactId>
			<version>6.2.5.Final</version>
			<optional>true</optional>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>${maven.compiler.source}</source>
					<target>${maven.compiler.target}</target>
					<encoding>${project.build.sourceEncoding}</encoding>
				</configuration>
			</plugin>
			<!-- Source -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-source-plugin</artifactId>
				<version>3.1.0</version>
				<inherited>true</inherited>
				<executions>
					<execution>
						<id>attach-sources</id>
						<goals>
							<goal>jar</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<excludeResources>true</excludeResources>
					<useDefaultExcludes>true</useDefaultExcludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<profiles>
		<profile>
			<id>release</id>
			<build>
				<plugins>
					<!-- Javadoc -->
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-javadoc-plugin</artifactId>
						<version>2.10.4</version>
						<executions>
							<execution>
								<id>attach-javadocs</id>
								<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>
						<configuration>
                            <!-- 改成你自己的路径 -->
							<executable>E:\_Gpg4win\GnuPG\bin\gpg.exe</executable>
						</configuration>
						<executions>
							<execution>
								<phase>verify</phase>
								<goals>
									<goal>sign</goal>
								</goals>
							</execution>
						</executions>
					</plugin>
					<plugin>
						<groupId>org.sonatype.central</groupId>
						<artifactId>central-publishing-maven-plugin</artifactId>
						<version>0.4.0</version>
						<extensions>true</extensions>
						<configuration>
							<!-- 这里的serverId是之前在settings.xml中配置的 -->
							<publishingServerId>sonatype-sticki</publishingServerId>
							<tokenAuth>true</tokenAuth>
						</configuration>
					</plugin>
				</plugins>
			</build>
		</profile>
	</profiles>

</project>

以下是对这份文档的一些说明:

  1. 项目基本信息:properties 以上的部分,虽然都是一些项目信息,但我建议你都保留下来,其中有一些是必须要有的,比如 namelicensesscm 这几个是必须存在的,其他的我不确定是不是必须的,但还是建议你保留。记得要改成自己的,不要直接复制了就用。

  2. 项目依赖:dependencies这部分没有要求,根据自己的项目需求来就好了。

  3. 打包插件:上传的jar包必须有 源代码、Javadoc、GPG 这三个部分,都是必须的,所以有三个部分的插件。

    由于我自己在本地打包调试的时候不需要这些东西,所以我把一部分插件放在了 profile 里,你 deploy 的时候需要勾选上配置,本地 install 则不需要。

    GPG 的插件需要修改下路径,否则会出现找不到 gpg.exe 的异常。

    最后面这个 central-publishing-maven-plugin 是用来发布jar包到平台上的,需要修改下 publishingServerId,内容对应前面改的 setting.xml 文件。

配置完pom文件后,你可以先 mvn install -P release 一下,看看有没有报错什么的。

如果你的 Maven 构建的时候出现异常,但异常信息是乱码的:

构建时异常

这种情况下我们给Maven修改下编码,在Maven的运行时参数中添加 -Dfile.encoding=GB2312 即可:

配置Maven编码

弄好之后再重新构建,就可以看到异常描述了:

Javadoc有很多警告,缺少 @return 标签,可以改一下,也可以不改,看你心情。

没别的问题就可以准备发布项目了。

发布项目

先 clean 然后再 deploy,会弹出窗口让你输入 GPG 的密码,验证成功后就会开始上传。

deploy

如果在 deploy 时出现了这样的异常:

Deployment 2c57742a-ff70-4f5c-aa75-5f50614a68eb (Deployment) failed while publishing

可以到 sonatype 的网站上查看失败的原因:

发布失败

如果一切顺利的话,你可以在 sonatype 的网站上看到你上传成功的但未发布的maven包:

发布jar包

这个时候我们点击 Publish ,Deployment的状态就会变成 publishing,意思是正在发布中,大概多十多分钟,它的状态会变为 published,这时候就正式发布成功了。

发布完成后,可以搜索到我们发布的 jar 包:

搜索我们jar包

后续maven中央仓库和阿里镜像仓库等都会自动同步,这样我们就成功发布了我们的项目了。之后如果升级的话,记得要把版本号进行更新,否则是发布不了的。

最后

为了防止有些小伙伴遇到其他奇奇怪怪的问题,这里贴一下官网的文档链接,但比较长,需要自己找噢:https://central.sonatype.org/register/central-portal/

终于完成啦~ 本文中发布的项目是我自己写的一个组件,maven坐标是:

<groupId>cn.sticki</groupId>
<artifactId>spel-validator</artifactId>
<version>0.0.2-beta</version>

GitHub地址也一起贴给大家:https://github.com/stick-i/spel-validator : 一个强大的 Java 参数校验包,基于 SpEL 实现,扩展自 javax.validation 包,几乎支持所有场景下的参数校验。 (github.com)

欢迎大家体验项目,也希望大家可以给我点个 star 支持一下呀~

关注我,分享更多技术干货~ 也可以订阅我的公众号 程序员阿杆,可以第一时间收到文章推送噢~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1650484.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C语言】用数组和函数实现扫雷游戏

用数组和函数实现扫雷游戏 游戏界面&#xff1a; 代码如下&#xff1a; game.h #pragma once #include <stdio.h> #include <stdlib.h> #include <time.h> #define EASY_COUNT 10 #define ROW 9 #define COL 9 #define ROWS ROW2 #define COLS COL2 //初始…

[正则表达式]正则表达式语法与运用(Regular Expression, Regex)

0. 在线工具 RegExr: Learn, Build, & Test RegEx 1. 场景列举 vim Linux命令行 sublime 编辑器 java、python等语言中 ... ... 不同场景、不同版本语法可能不一样 2. 以下示例数据与基本语法 &2024 &As20242024# 2024sA#abdcefgha_bdcefghABASDSADAASDASD…

经常发文章的你是否想过定时发布是咋实现的?

前言 可乐他们团队最近在做一个文章社区平台,由于人手不够,前后端都是由前端同学来写。后端使用 nest 来实现。 某一天周五下午,可乐正在快乐摸鱼,想到周末即将来临,十分开心。然而,产品突然找到了他,说道:可乐,我们要做一个文章定时发布功能。 现在我先为你解释一…

已经做了小20年电商梦的腾讯,终于找到了破局的方向~

我是王路飞。 随着短视频的爆火、抖音电商成功开辟出短视频/直播带货的电商新赛道。 已经做了小20年电商梦的腾讯&#xff0c;终于找到了破局的方向~ 这个方向&#xff0c;就是被腾讯马老板亲口认证为&#xff1a;全村&#xff08;全公司&#xff09;希望所在的视频号。 内…

Python-100-Days: Day11 Files and Exception

1.读取csv文件 读取文本文件时&#xff0c;需要在使用open函数时指定好带路径的文件名&#xff08;可以使用相对路径或绝对路径&#xff09;并将文件模式设置为r&#xff08;如果不指定&#xff0c;默认值也是r&#xff09;&#xff0c;然后通过encoding参数指定编码&#xf…

基于FPGA的DDS波形发生器VHDL代码Quartus仿真

名称&#xff1a;基于FPGA的DDS波形发生器VHDL代码Quartus仿真&#xff08;文末获取&#xff09; 软件&#xff1a;Quartus 语言&#xff1a;VHDL 代码功能&#xff1a; DDS波形发生器VHDL 1、可以输出正弦波、方波、三角波 2、可以控制输出波形的频率 DDS波形发生器原理…

手撸Mybatis(五)——连接数据库进行insert,update和delete

本专栏的源码&#xff1a;https://gitee.com/dhi-chen-xiaoyang/yang-mybatis。 引言 在上一章中&#xff0c;我们成功实现了数据库的连接&#xff0c;以及单个字段的查询、resultType映射查询、resultMap映射查询。在本章&#xff0c;我们将讲解关于增加、修改和删除操作。 …

【MATLAB源码-第204期】基于matlab的语音降噪算法对比仿真,谱减法、维纳滤波法、自适应滤波法;参数可调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 语音降噪技术的目的是改善语音信号的质量&#xff0c;通过减少或消除背景噪声&#xff0c;使得语音更清晰&#xff0c;便于听者理解或进一步的语音处理任务&#xff0c;如语音识别和语音通讯。在许多实际应用中&#xff0c;如…

MySQL45讲(一)(40)

回顾binlog_formatstatement STATEMENT 记录SQL语句。日志文件小&#xff0c;节约IO&#xff0c;但是对一些系统函数不能准确复制或不能复制&#xff0c;如now()、uuid()等 在RR隔离级别下&#xff0c;binlog_formatstatement 如果执行insert select from 这条语句是对于一张…

动态规划算法:简单多状态问题

例题一 解法&#xff08;动态规划&#xff09;&#xff1a; 算法思路&#xff1a; 1. 状态表⽰&#xff1a; 对于简单的线性 dp &#xff0c;我们可以⽤「经验 题⽬要求」来定义状态表⽰&#xff1a; i. 以某个位置为结尾&#xff0c;巴拉巴拉&#xff1b; ii. 以某个位置为起…

通过高效的升级计划控制云成本

快速迁移到云以及使用和成本的复杂性使得公司迫切希望减少浪费并控制其支出。更糟糕的是&#xff0c;动荡的经济让决策者紧张不安&#xff0c;他们考虑削减成本措施并优先考虑锁定收入。 如果没有正式的 FinOps 或成本优化策略&#xff0c;公司很容易看到云费用如滚雪球般失控…

一键解密,网络安全神器现已问世!

一、简介 当前版本V1.1这款工具是一款功能强大的网络安全综合工具&#xff0c;旨在为安全从业者、红蓝对抗人员和网络安全爱好者提供全面的网络安全解决方案。它集成了多种实用功能&#xff0c;包括解密、分析、扫描、溯源等&#xff0c;为用户提供了便捷的操作界面和丰富的功…

UDP多播

1 、多播的概念 多播&#xff0c;也被称为组播&#xff0c;是一种网络通信模式&#xff0c;其中数据的传输和接收仅在同一组内进行。多播具有以下特点&#xff1a; 多播地址标识一组接口&#xff1a;多播使用特定的多播地址&#xff0c;该地址标识一组接收数据的接口。发送到多…

现场面试题

这里写目录标题 1.sql1.1 只保留学生的最新成绩1.2 统计通话号码数1.3 更新地址 2.基础题2.1 请求序列第N位的值: 0, 1, 1, 2, ,3, 5, 8, 13, 21, 34.....第N位的值2.2 请写一段java代码&#xff0c;输出存在重复字母的单词 1.sql 1.1 只保留学生的最新成绩 表student中记录学…

每日一题(PTAL2):列车调度--贪心+二分

选择去维护一个最小区间 代码1&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n;cin>>n;int num;vector <int> v;int res0;for(int i0;i<n;i){cin>>num;int locv.size();int left0;int rightv.size()-1;while(left<…

C++变量的作用域与存储类型

一 变量的作用域和存储类型 1 变量的作用域(Scope) 指在源程序中定义变量的位置及其能被读写访问的范围分为局部变量(Local Variable)和全局变量(Global Variable) 1&#xff09;局部变量(Local Variable) 在语句块内定义的变量 形参也是局部变量 特点&#xff1a; 生存期是…

AIGC-3D数字人技术:高效助推各行业数字化水平升级

从“互联网”到“人工智能”&#xff0c;数字员工作为一种全新的交互形式&#xff0c;对企业有着重要的作用&#xff0c;企业、品牌通过数字人的AI语音交互、AI播报等核心功能&#xff0c;可以有效推动企业提升数字水平。 作为3D、AI虚拟数字人技术服务商及方案提供商&#xff…

为什么都喜欢用串口通讯?那为什么还用RS485,SPI和I2C?

1、为什么都喜欢用串口通讯&#xff1f; 之前在做单片机产品的时候&#xff0c;用的最多的就是串口通讯&#xff0c;凡是单片机的外设&#xff0c;优先选用带串口功能的&#xff0c;比如蓝牙模块&#xff0c;WIFI模块&#xff0c;4G模块&#xff0c;电表和显示屏等等。 为什么都…

科研学习|可视化——ggplot2版本的网络可视化

ggplot2是R语言中一个非常流行的数据可视化包&#xff0c;它也可以用于网络可视化。以下是三个基于ggplot2并专门用于网络可视化的R包&#xff1a; ggnet2: 这个包的使用方法与传统的plot函数相似&#xff0c;易于使用。更多信息可在其官方页面查看&#xff1a;ggnet2 geomnet…

KUKA机器人故障报警信息处理(一)

1、KSS00276 机器人参数不等于机器人类型 ①登录专家模式 ②示教器操作&#xff1a;【菜单】—【显示】—【变量】—【单个】 ③名称输入&#xff1a;$ROBTRAFO[] 新值&#xff1a;TRAFONAME[] ④点击【设定值】。 2、电池报警&#xff1a; ①“充电电池警告-发现老化的蓄电池…