发布构件至Maven中央库

背景

做了一些开源项目, 可以开箱即用, 为了能让用户快速体验, 最佳方案就是把其构件发布至中央库, 用户按文档导入该依赖, 拷贝文档的测试用例代码, 运行即可看到结果; 为用户调研权衡节省时间.

下文将介绍如何把源码成功发布至Maven中央库的全过程.

样例项目

该项目的项目目录结构, pom.xml相关配置符合发布要求, 且已发布成功, 并会进行不定期更新, 首次发布的同学可参考对比.

注册Sonatype账户

该站点用于提交构件发布的申请及相关问题.

注: 请记住注册的用户名和密码, 在以后会经常用到.

提交发布申请

根据提示填写相关信息, 关键信息介绍如下:

  • group id: 就是别人在使用你的构件的时候在pom.xml里面进行定位的坐标的一部分,而且尽量应该是你的站点的url倒序,参考java包命名的规范,有时候工作人员会想你确认你是否是这个站点url的拥有者,这里由于我已经购买了arccode.net域名的所有权,所以我填写的就是“net.arccode”.
  • project url: 这个是项目的站点,一般是用作说明的.
  • SCM url: 这个构件的源代码的url,便于别人查看源代码,当然这个得是公网能够访问的,不要是什么内部的svn地址什么的哈,笔者目前用的是github.

其他的就没有什么了,提交之后就等工作人员离开确认吧,有时候工作人员会问你些你没有明确的内容,只需要回答就好.需要注意的是,这个系统的工作人员是在美国上班的,经过我的等待和观察,他们会在北京时间的22:00开始上班、处理issue,所以在这个时间之前就不要去查询状态了.

等到工作人员在你创建的issue下面回复你说“配置已经修改……”(还有几个链接)的时候就说明审批已经通过了,你就可以进行构件的上传了.

GPG

在上传构件之前,需要准备GPG以便对发布的文件进行签名.

1.查看是否安装成功

gpg --version

能够显示 GPG 的版本信息,说明安装成功了.

2.生成密钥对

gpg --gen-key

此时需要输入姓名、邮箱等字段,其它字段可使用默认值,此外,还需要输入一个Passphase,相当于一个密钥库的密码,一定不要忘了,也不要告诉别人,最好记下来,因为后面会用到.

3.查看公钥

gpg --list-keys

输出如下信息:

1
2
3
4
pub   rsa2048 2017-10-13 [SC] [有效至:2019-10-13]
28FB909499763F5AC432159E4ADB67A5CD37AB08
uid [ 绝对 ] arccode <zuitiku@gmail.com>
sub rsa2048 2017-10-13 [E] [有效至:2019-10-13]

可见这里的公钥的ID是:28FB909499763F5AC432159E4ADB67A5CD37AB08,稍后就会用到.

4.将公钥发布到 PGP 密钥服务器

gpg --keyserver hkp://pool.sks-keyservers.net --send-keys 28FB909499763F5AC432159E4ADB67A5CD37AB08

此后,可使用本地的私钥来对上传构件进行数字签名,而下载该构件的用户可通过上传的公钥来验证签名,也就是说,大家可以验证这个构件是否由本人上传的,因为有可能该构件被坏人给篡改了.

5.查询公钥是否发布成功

gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 28FB909499763F5AC432159E4ADB67A5CD37AB08

实际上就是从key server上通过公钥ID来接收公钥,此外,也可以到sks-keyservers.net上通过公钥ID去查询.

修改Maven配置文件

文件位置: MAVEN_HOME/conf/setting.xml

1
2
3
4
5
6
7
8
9
10
11
<settings>
...
<servers>
<server>
<id>oss</id>
<username>用户名</username>
<password>密码</password>
</server>
</servers>
...
</settings>

使用自己注册的Sonatype账号的用户名与密码来配置以上server信息.

修改项目pom.xml

添加GPG plugin(plugins节点下)

1
2
3
4
5
6
7
8
9
10
11
12
13
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>

添加项目描述信息(project节点下)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<name>LittleBird MyBatis Generator Core</name>
<description>LittleBird MyBatis Generator Core - a code generator for MyBatis and iBatis.</description>
<url>https://github.com/arccode/littlebird-mybatis-generator-core</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>arccode</name>
<email>zuitiku@gmail.com</email>
</developer>
</developers>
<scm>
<url>https://github.com/arccode/littlebird-mybatis-generator-core</url>
<tag>littlebird-mybatis-generator-0.0.1</tag>
</scm>
1
2
3
4
5
6
7
8
9
10
11
 <distributionManagement>
<site>
<id>master</id>
<name>LittleBird Mybatis Generator Core GitHub Pages</name>
<url>git@github.com:arccode/littlebird-mybatis-generator-core.git</url>
</site>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>

注: 以上pom.xml必须包括:name、description、url、licenses、developers、scm等基本信息; 此外,snapshotRepository与repository中的id一定要与setting.xml中server的id保持一致.

上传构件至OSS中

mvn clean deploy

当执行以上Maven命令时,会自动弹出一个对话框,需要输入上面提到的Passphase,它就是通过GPG密钥对的密码,只有自己才知道.随后会看到大量的upload信息,而且速度比较慢,经常会timeout,需要反复尝试.

注意:此时上传的构件并未正式发布到中央仓库中,只是部署到OSS中了,下面才是真正的发布.

若多次发布不成功可使用另一个指令

mvn clean deploy -Dgpg.passphrase=密码

在OSS中发布构件

url: https://oss.sonatype.org

用户名和密码为第一步注册的Sonatype账号

在OSS中,使用自己的Sonatype账号登录后,可在Staging Repositories中查看刚才已上传的构件,这些构件目前是放在Staging仓库中,可进行模糊查询,快速定位到自己的构件.此时,该构件的状态为Open,需要勾选它,然后点击Close按钮.接下来系统会自动验证该构件是否满足指定要求,当验证完毕后,状态会变为Closed,最后,点击Release按钮来发布该构件.

通知Sonatype 构件发布成功

需要在曾经创建的 Issue 下面回复一条“构件已成功发布”的评论,这是为了通知 Sonatype 的工作人员为需要发布的构件做审批,发布后会关闭该 Issue.

等待构件审批通过

没错,还是要等,也许又是 1 ~ 2 天.同样,当审批通过后,将会收到邮件通知.

从中央仓库中搜索构件

url: http://search.maven.org/

过一段时间可以在另一些仓库中搜索到, 例如 http://mvnrepository.com/

第一次发布很痛苦, 但只要这次发布成功了, 以后发布就很简单了.

maven打包时可能碰到的问题

使用jdk1.6编译时报 OutOfMemoryError

该问题表示对内存不足, 要么将jdk版本升级至jdk1.7及更高, 要么增加堆内存大小; 为了兼容性笔者选择增加对内存大小.

Windows环境

找到文件%M2_HOME%\bin\mvn.bat ,这就是启动Maven的脚本文件,在该文件中你能看到有一行注释为:
@REM set MAVEN_OPTS=-Xdebug -Xnoagent -Djava.compiler=NONE…
它的意思是你可以设置一些Maven参数,我们就在注释下面加入一行:

set MAVEN_OPTS= -Xms128m -Xmx512m

Linux环境

编辑文件/etc/profile

export MAVEN_OPTS=-Xmx512m

OSX环境

编辑文件~/.bash_profile

export MAVEN_OPTS=-Xmx512m

使用jdk1.8生成javadoc时报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
/Users/ac/workspace/github/fastdfs-client-java/src/main/java/org/csource/fastdfs/StorageClient.java:1009: 警告: java.io.IOException没有 @throws
public int truncate_file(String group_name, String appender_filename) throws IOException, MyException {
^
/Users/ac/workspace/github/fastdfs-client-java/src/main/java/org/csource/fastdfs/StorageClient.java:1009: 警告: org.csource.common.MyException没有 @throws
public int truncate_file(String group_name, String appender_filename) throws IOException, MyException {
^
Command line was: /Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/jre/../bin/javadoc @options @packages
Refer to the generated Javadoc files in '/Users/ac/workspace/github/fastdfs-client-java/target/apidocs' dir.
at org.apache.maven.plugin.javadoc.AbstractJavadocMojo.executeJavadocCommandLine(AbstractJavadocMojo.java:5163)
at org.apache.maven.plugin.javadoc.AbstractJavadocMojo.executeReport(AbstractJavadocMojo.java:2075)
at org.apache.maven.plugin.javadoc.JavadocJar.execute(JavadocJar.java:188)
... 21 more
[ERROR]
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

经查得知,在JDK 8中,Javadoc中添加了doclint,而这个工具的主要目的是旨在获得符合W3C HTML 4.01标准规范的HTML文档,在JDK 8中,已经无法获取如下的Javadoc,除非它满足doclint:

  • 不能有自关闭的HTML tags,例如<br/>或者<a id="x"/>
  • 不能有未关闭的HTML tags,例如有<ul>而没有</ul>
  • 不能有非法的HTML end tags,例如</br>
  • 不能有非法的HTML attributes,需要符合doclint基于W3C HTML 4.01的实现
  • 不能有重复的HTML id attribute
  • 不能有空的HTML href attribute
  • 不能有不正确的嵌套标题,例如类的文档说明中必须有<h3>而不是<h4>
  • 不能有非法的HTML tags,例如List<String>需要用<>对应的实体符号
  • 不能有损坏的@link references
  • 不能有损坏的@param references,它们必须匹配实际的参数名称
  • 不能有损坏的@throws references,第一个词必须是一个类名称

注意违反这些规则的话,将不会得到Javadoc的输出。

方案一

profile中禁用doclint,

1
2
3
4
5
6
7
8
9
10
11
<profiles>
<profile>
<id>disable-javadoc-doclint</id>
<activation>
<jdk>[1.8,)</jdk>
</activation>
<properties>
<additionalparam>-Xdoclint:none</additionalparam>
</properties>
</profile>
</profiles>

方案二

maven-javadoc-plugin中禁用doclint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</execution>
</executions>
</plugin>

可发布到maven中央库的pom.xml配置

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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<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>net.arccode</groupId>
<artifactId>fastdfs-client-java</artifactId>
<packaging>jar</packaging>
<version>1.27.0</version>

<name>fastdfs-client-java</name>
<description>FastDFS client for java</description>
<url>https://github.com/arccode/fastdfs-client-java</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.test.failure.ignore>true</maven.test.failure.ignore>
<maven.test.skip>true</maven.test.skip>
<jdk.version>1.6</jdk.version>
</properties>

<licenses>
<license>
<name>Berkeley Source Distribution</name>
<url>http://www.linfo.org/bsdlicense.html</url>
</license>
</licenses>

<developers>
<developer>
<name>arccode</name>
<email>zuitiku@gmail.com</email>
</developer>
</developers>

<scm>
<url>https://github.com/arccode/fastdfs-client-java</url>
<tag>fastdfs-client-java-1.27.0</tag>
</scm>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<encoding>UTF-8</encoding>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.5</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>site</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>jar</goal>
</goals>
<!-- jdk>=1.8必须配置此选项, 详见: http://www.arccode.net/publish-artifact-to-maven-central-repository.html
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration> -->

</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>org.mybatis.generator.api.ShellRunner</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/src.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>bundle</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<arguments>-Prelease</arguments>
</configuration>
</plugin>
<!-- GPG -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<reporting>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jdepend-maven-plugin</artifactId>
<version>2.0</version>
</plugin>
</plugins>
</reporting>

<distributionManagement>
<site>
<id>master</id>
<name>FastDFS client for java GitHub Pages</name>
<url>git@github.com:arccode/fastdfs-client-java.git</url>
</site>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>


</project>

本pom.xml中配置了assembly, 将把文档/jar包/readme等(具体看需求而定)打包成一个bundle.zip文件, 因此需要配置src.xml; 其配置如下:

文件位置:

${project.basedir}/src/main/assembly/src.xml
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
<!--

Copyright 2006-2017 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">

<id>bundle</id>
<formats>
<format>zip</format>
</formats>
<fileSets>
<fileSet>
<includes>
<include>${project.basedir}/README*</include>
<include>${project.basedir}/LICENSE*</include>
<include>${project.basedir}/NOTICE*</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>lib</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
<fileSet>
<directory>${project.build.directory}/site</directory>
<outputDirectory>docs</outputDirectory>
<includes>
<include>**/*.*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

结束语

经实践证明, 此后的发布超级简单,

  1. 构件准备好之后,在命令行上传构建, mvn clean deploy
  2. https://oss.sonatype.org/“close”并“release”构件;
  3. 等待同步好(大约2小时多)之后,就可以使用了

本序列文章

参考资料

转载

本文出自<<arccode>>, 欢迎转载, 转载请注明出处.