将java项目发布到maven中央仓库(踩坑大全)

2023-05-16

前言:

第一次将构件发布到中央仓库,真的不是一件轻松的事情,网络上有很多其他文章大都不会把坑帮你描述清楚。所以觉得非常有必要把些步骤记下来,让大家少走点弯路。

一、maven中央仓库简介

相关内容介绍
maven
Sonatype中央仓库官网:http://www.sonatype.org/

二、发布的前置工作

2.1注册账户

注册地址:https://issues.sonatype.org/secure/Signup!default.jspa

坑: 注册时Username 一定不要使用中文。老外对中文支持不好。后续一堆问题,还要重建账户。

注册完登陆,地址:https://issues.sonatype.org/login.jsp

2.2 创建一个 Issue

创建地址:https://issues.sonatype.org/secure/CreateIssue.jspa?issuetype=21&pid=10134

坑1: 通过控制面板上的创建按钮创建记得选择类别:
Community Support - Open Source Project Repository Hosting

坑2:group Id:这个必须要注意,如果你用的是GitHub, 一定要是 com.github.你的github用户名, 
例如项目地址是: https://github.com/xxx/Common, 那groupId就是 com.github.xxx

如果你有自己的域名和项目地址也可以,官方人员会询问你是否有这个域名的所有权。

在你项目的pom里一定要使用这个groupId,

如果是自定义域名,必须添加域名解析如下图所示,以下是我使用自定义域名后的官方回复。
在这里插入图片描述

2.3 使用 GPG 生成密钥对

在等待Issue的时候可以先把密钥搞好

2.3.1 GPG是什么?

说明文档:http://central.sonatype.org/pages/working-with-pgp-signatures.html

大体是说,部署组件到中央仓库要求需要GPG签名文件,而GnuPG 或者 GPG 是OpenPGP标准的一个实现,能够管理签名相关的东西,然后这个文档将告诉你如何生成自己的签名Key Pair 密钥对以及分发到 key server 以便别人可以验证签名(最后其实就是在发布的时候,Sonatype会通过key server上的信息进行验证deploy文件的有效性)

2.3.2 安装 GnuPG

下载地址 :https://www.gnupg.org/download/


Windows 系统,直接下载 Gpg4win。

坑:下载的时候有个坑,会弹出一个捐助页面,然后没有下载的地方,也没有自动开始下载.
感觉好像不捐助就不能下载一样.其实在下载页面下面有个All Downloads,
里面有个连接 files.gpg4win.org,在这里找到与下载页面上的最新版相同的版本号下载即可

安装过程中在选择组件的时候,除了默认必须安装的,其他取消即可

安装完成后,打开CMD 执行 gpg --version 验证安装是否成

2.3.3 生成密钥对
gpg --gen-key
Real name: 输入名字(注意不要用中文)
Email address: 邮箱
You selected this USER-ID:
"xxxxxx@qq.com"
Change (N)ame, (E)mail, or (O)kay/(Q)uit? o

之后往下,会让你输入Passphase(输入两次),相当于密钥库密码,不要忘记。

2.3.4 查看公钥
gpg --list-keys
#其中,pub表示是公钥,而sub表示私钥。 

记住pub

2.3.5 将公钥发布到 PGP 密钥服务器
gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 你的公钥指纹 #即pub   

这里可能是传输的原因要稍等,或者你也可以执行两次。

2.3.6 查询公钥是否发布成功
gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 你的公钥指纹 #即pub   
以下注意:
坑: 一般网上的文档就说明这样发布就可以了实际上,后面部署会报错,错误如下截图。

failureMessage No public key: Key with id: (1fcda02dd63733fe) was not ableto be located on http://pgp.mit.edu:11371/. Uploadyour public key and try the operation again.
failureMessage No public key: Key with id: (1fcda02dd63733fe) was not ableto be located on http://keyserver.ubuntu.com:11371/.Upload your public key and try the operation again.
failureMessage No public key: Key with id: (1fcda02dd63733fe) was not ableto be located on http://pool.sks-keyservers.net:11371/.Upload your public key and try the operation again.

从上面我们发现有三个 key-servers 是 Sonatype公司要用到的,Sonatype公司会在上面任意一个key-servers上进行搜索公钥,具体的key-servers 为:
http://pgp.mit.edu:11371
http://keyserver.ubuntu.com:11371
http://pool.sks-keyservers.net:11371

这个要注意了,这个是带端口的,这个我在实际操作中,也踩了这个坑,一开始我上传公钥到下面中的一个(注意,没有带端口号)

gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 你的公钥指纹
gpg --keyserver hkp://pgp.mit.edu --send-keys 你的公钥指纹
gpg --keyserver hkp://keyserver.ubuntu.com --send-keys 你的公钥指纹

注意了,协议不是http,而是 hkp,要看清楚了,实际上是需要带端口号上传的:

gpg --keyserver hkp://pool.sks-keyservers.net:11371 --send-keys 你的公钥指纹
gpg --keyserver hkp://pgp.mit.edu:11371 --send-keys 你的公钥指纹
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --send-keys 你的公钥指纹

没有成功的话要注意Sonatype反馈了什么信息然后根据信息进行修改。

上面是将公钥发布到 GPG key-servers 的命令,我们可以通过以下命令查看具体的公钥信息:

gpg --keyserver hkp://pool.sks-keyservers.net:11371 --recv-keys 你的公钥指纹
gpg --keyserver hkp://pgp.mit.edu:11371 --recv-keys 你的公钥指纹
gpg --keyserver hkp://keyserver.ubuntu.com:11371 --recv-keys 你的公钥指纹

三、发布maven工程到中央仓库

3.1 Issue通过

官方会回复你,如下图所示。你就可以发布项目的
在这里插入图片描述

3.2 修改maven配置

修改maven全局配制文件 settings.xml,在maven安装目录的conf文件夹下。注意用户名密码即你注册jira账户的用户名和密码

<servers>
    <server>
        <id>oss</id>
        <username>用户名</username>
        <password>密码</password>
    </server>
</servers>
坑:通过mvn --version 查看你本机的maven安装目录。而非idea自带maven,否则一会儿执行发布命令可能会报错。

3.2 修改pom文件

添加如下信息:

<project>
    ...
    <name>Common</name>
    <description>Common is a rapid development kit.</description>
    <url>http://www.example.com/</url>
    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</naurl
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>
    <developers>
        <developer>
            <name>username</name>
            <email>email@foxmail.com</email>
        </developer>
    </developers>
    <scm>
        <connection>scm:git:git@github.com:xxx/yyy.git</connection>
        <developerConnection>scm:git:git@github.com:xxx/yyy.git</developerConnection>
        <url>git@github.com:xxx/yyy.git</url>
    </scm>
    
    <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>
                </plugins>
            </build>
            <distributionManagement>
                <snapshotRepository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
                </snapshotRepository>
                <repository>
                    <id>oss</id>
                    <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
                </repository>
            </distributionManagement>
        </profile>
    </profiles>
    ...
</project>

pom.xml 中必须包括:name、description、url、licenses、developers、scm 等基本信息,使用了 Maven 的 profile 功能,只有在 release 的时候才创建源码包、文档包、使用 GPG 进行数字签名。

这里着重介绍一下scm 参考了(https://blog.csdn.net/xiajiqiu/article/details/77607492)

3.2.1Subversion on your own server:
<scm>
  <connection>scm:svn:http://subversion.example.com/svn/project/trunk/</connection>
  <developerConnection>scm:svn:https://subversion.example.com/svn/project/trunk/</developerConnection>
  <url>http://subversion.example.com/svn/project/trunk/</url>
</scm>
3.2.2 Git hosted on GitHub:
<scm>
  <connection>scm:git:git://github.com/xxx/yyy.git</connection>
  <developerConnection>scm:git:ssh://github.com:xxx/yyy.git</developerConnection>
  <url>http://github.com/simpligility/xxx/tree/master</url>
</scm>
3.2.3 Git hosted on Gitee:
<scm>
     <tag>master</tag>
     <url>https://gitee.com/xxx/yyy.git</url>
     <connection>scm:git:git@gitee.com/xxx/yyy.git</connection>
     <developerConnection>scm:git:git@gitee.com/xxx/yyy.git</developerConnection>
</scm>
3.2.4 Git hosted on BitBucket:
<scm>
  <connection>scm:git:git://bitbucket.org/simpligility/ossrh-pipeline-demo.git</connection>
  <developerConnection>scm:git:ssh://bitbucket.org:simpligility/ossrh-pipeline-demo.git</developerConnection>
  <url>https://bitbucket.org/simpligility/ossrh-pipeline-demo/src</url>
</scm>
3.2.5 Mercurial on BitBucket:
<scm>
  <connection>scm:git:git://bitbucket.org/simpligility/ossrh-pipeline-demo.git</connection>
  <developerConnection>scm:git:ssh://bitbucket.org:simpligility/ossrh-pipeline-demo.git</developerConnection>
  <url>https://bitbucket.org/simpligility/ossrh-pipeline-demo/src</url>
</scm>
3.2.6 Git on Apache Git Server from Apache Maven:
<scm>
  <connection>scm:git:https://git-wip-us.apache.org/repos/asf/maven.git</connection>
  <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/maven.git</developerConnection>
  <url>https://github.com/apache/maven/tree/${project.scm.tag}</url>
  <tag>master</tag>
</scm>

此外,snapshotRepository 与 repository 中的 id 一定要与 setting.xml 中 server 的 id 保持一致。
如果是多模块项目的话,只需要在父 pom.xml 中声明这些,子 pom.xml 中只需要修改相应的一些信息,如 name 标签。
由于我使用的是jdk8,对doc的格式要求更严,不标准的doc注释会报错,这时候可以通过在doc插件中配制additionalparam参数,上面代码里已经配过了.但这只是临时解决方案,还是尽量使用标准的doc注释吧.

坑:在这里maven-gpg-plugin 可能标红,通过 
mvn dependency:get -DrepoUrl=http://repo.maven.apache.org/maven2/ -Dartifact=org.apache.maven.plugins:maven-gpg-plugin:1.6
手动下载,还是标红。直接忽略。不影响执行上传命令。

3.3 执行上传命令

#发布前检查version 是否已经修改成release版本。
mvn clean deploy -P release

当执行以上 Maven 命令时,会自动弹出一个对话框,需要输入上面提到的 Passphase,它就是刚才设置的 GPG 密钥库的密码。
注意:此时上传的构件并未正式发布到中央仓库中,只是部署到 OSS 中了,下面才是真正的发布。

如果发布报401错误,请再次检查 snapshotRepository 与 repository 中的 id 一定要与 setting.xml 中 server 的 id 保持一致。

四、在中央仓库发布

4.1 提交审核

使用 Jira 账号登录 https://oss.sonatype.org。注意这里的issue的网址不同。
登陆以后在控制面板的Staging Repositories 可以查看到刚提交的内容。

4.2 执行close

点击【Close】按钮,然后等待,时不时你电机系【Refresh】按钮,会把进度显示在下面的【Activity】

我们可以对比Avtivity执行Close以后成功或者失败的信息。如图4.2和4.3所示:
4.2
点开错误信息我们可以查看到错误详情。按照错误提示我们修正好重新提交再执行Close。直到成功。
错误提示
4.3

4.3 如果Close校验完成。则按钮Release可用,执行它。

这里Release不代表你已经提交到中央仓库了。而是提交到sonatype了。需要在issue添加备注提醒官方审核。如下图 我简单写了。Component has been successfully issued。
在这里插入图片描述

4.4 耐心等待官方审核。

审核成功会收到回复。例如:

什么意思呢?意思就是说10分钟内,别人就可以直接通过在pom中引入你的项目并下载依赖了,但是如果要在http://search.maven.org/ 上搜索到你的组件,还需要等待至少两个小时,因为http://search.maven.org/ 是两个小时刷新一次索引的。

我们可以maven中央仓库中查看自己的组件了:
https://repo1.maven.org/maven2/你的groupId将.变成目录分隔符/artifactId
至此,我们就完成了组件的发布了。

4.5 迭代版本的发布。

第一次发布比较麻烦,后续因为代码更新版本迭代。只需重复 3.3~4.3步骤即可。

五、使用Nexus Staging Maven plugin

简介

在Close & Release 文档中(
http://central.sonatype.org/pages/releasing-the-deployment.html#close-and-drop-or-release-your-staging-repository
),最后面有一段话:

Note thatdeploying with the Nexus Staging Maven plugin or Ant tasks will, by default,automatically attempt to close the staging repository upon deployment and canbe used to release the staging repository from the command line as well. Thisallows you to avoid logging into the OSSRH user interface altogether. Moredetails can be found in the Maven and Ant sections of this guide.

翻译一下,大概意思就说:你可以使用 Nexus Staging Maven 插件来进行你的组件发布,这样就不需要登录 OSSRH 进行界面操作了,减少了发布的复杂度。

注: OSSRH实际上就是https://oss.sonatype.org/

使用该插件发布

文档地址:http://central.sonatype.org/pages/apache-maven.html#nexus-staging-maven-plugin-for-deployment-and-release
标题很明显,就是说你可以使用 Nexus Staging 的Maven 插件实现组件的deploy和release,这样你就不需要去登录 OSSRH 网站点击Close,点击Release了。

使用很简单,在你项目的 POM中加入:

<!-- Nexus Staging Plugin, auto deploy close and release -->
<plugin>
  <groupId>org.sonatype.plugins</groupId>
  <artifactId>nexus-staging-maven-plugin</artifactId>
  <version>1.6.8</version>
  <extensions>true</extensions>
  <configuration>
     #之前步骤settings.xml中的servers中设置了这个ID
     <serverId>oss</serverId>
     #https://oss.sonatype.org/
     <nexusUrl>https://oss.sonatype.org/</nexusUrl>
     #在Staging关闭后是否自动Release,如不是自动,就需要手动,
     #你可以登录OSSRH去手动点击Release也可以自己本地执行命令:
	 #mvn nexus-staging:release
	 #当然也可以删除:
	 #mvn nexus-staging:drop 
     <autoReleaseAfterClose>true</autoReleaseAfterClose>
  </configuration>
</plugin>

发布命令和原来一样:

mvn clean deploy –P release –Dgpg.passphrse=xxxxx #xxx是你的密钥对的密码
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将java项目发布到maven中央仓库(踩坑大全) 的相关文章

  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 为什么 i++ 不是原子的?

    Why is i Java 中不是原子的 为了更深入地了解 Java 我尝试计算线程中循环的执行频率 所以我用了一个 private static int total 0 在主课中 我有两个线程 主题 1 打印System out prin
  • Java EE:如何获取我的应用程序的 URL?

    在 Java EE 中 如何动态检索应用程序的完整 URL 例如 如果 URL 是 localhost 8080 myapplication 我想要一个可以简单地将其作为字符串或其他形式返回给我的方法 我正在运行 GlassFish 作为应
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • AWS 无法从 START_OBJECT 中反序列化 java.lang.String 实例

    我创建了一个 Lambda 函数 我想在 API 网关的帮助下通过 URL 访问它 我已经把一切都设置好了 我还创建了一个application jsonAPI Gateway 中的正文映射模板如下所示 input input params
  • Maven中archetype.xml和archetype-metadata.xml有什么区别

    我正在尝试向我的原型添加额外的变量 具体来说 我的原型包含一个 logback xml 文件 我想用我从原型生成的项目的名称填充日志文件名 我正在执行此处答案中的说明将额外的属性传递给 Maven archetype generate ht
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 获取 JVM 上所有引导类的列表?

    有一种方法叫做findBootstrapClass对于一个类加载器 如果它是引导的 则返回一个类 有没有办法找到类已经加载了 您可以尝试首先通过例如获取引导类加载器呼叫 ClassLoader bootstrapLoader ClassLo
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo

随机推荐