今天有朋友和我聊天说笔者已经有两天没有写文章了,都去干嘛了?我很无奈地回答说被maven弄自闭了。到底是什么样的问题导致我花了这么长时间去解决它?这篇文章告诉你。
笔者前几天一直在看Hotspot提供的tools包的源码,并试图去进行了改造和拓展,最后小有成就完成了第一个版本的虚拟机监控API:vmconsole,这不是重点,重点是在后面。我将它打成了jar包,并且想分享出去,让其他开发者也能使用,第一时间想到的就是Maven,如果我把它发布到Maven仓库不就可以了吗?于是开始笔者便开始了爬坑之路。
笔者在这里先为自己的作品打个预广告,欢迎广大编程爱好者使用以及提供意见和建议,同时笔者希望能得到你的小星星鼓励O(∩_∩)O,后续也会有专门的文章介绍该作品。
JVM虚拟机监控API:VmConsole-Api
这是笔者第一次将自己的项目发布到Maven仓库中,其中的步骤都不清楚,于是我就各种谷歌百度,实在解决不了就找其他人求助,简单的问题成功得以解决,可最关键的问题最后还是自己解决的,接下来就抛出我遇到的问题吧,答案以及解决办法后面会给出。
本地仓库是在每个开发者电脑上,一般在c:/user/.m
文件目录下;私有仓库是个人或组织建立的仓库,需要在全局settings.xml中配置仓库地址;中央仓库算是整个Maven存储的核心仓库,所有开发者都可以在其中获取资源。那么这个问题就解决了,为了让开发者方便地获取该依赖,我需要把jar包发布到中央仓库。
这个问题是笔者遇到的主要问题,我的项目并不是Maven项目,网上一大堆的教程全都是Maven项目如何发布到中央仓库,如果我的是Maven项目也不至于忙活这么久,我的项目正是非Maven项目,一个纯Java的,其中还包含了jdk的jar包,正因为jdk提供的这些jar包在Maven仓库中没有,所以我无法把我的项目改成Maven项目,其中的很多类必须依托于这些jar包。所以现在的问题就转换成了如何把已经打包好了的jar包发布到中央仓库。
简述一下我的做法吧,下面会给出完整的步骤,这也是笔者目前为止想到的唯一的办法,如果读者有更好的方法,希望你和我联系一下,笔者也学习学习。要传到中央仓库还是得需要Maven项目,所以我新建了一个空的Maven项目,然后将jar包先安装到本地仓库,在这个空的Maven项目中引入这个jar的本地依赖,再在pom中配置assembly插件把依赖包合并到一个jar包然后发布(启发来源于Springboot,因为Springboot的Maven项目中有配置这个插件),最后将整个项目发布到nexus中(仓库管理中心),在引入依赖的时候不能单纯的引入这个项目,而是引入项目中合并的那个jar,在依赖中配置classifier即可。
接下来贴出我的完整步骤,其中代码部分有点长,贴出代码的目的是方便有遇到同样情况的人粘贴复制内容,读者大可略过,只看文字或图片。
首先需要在https://issues.sonatype.org/secure/Dashboard.jspa注册账号,Sonatype通过JIRA来管理OSSRH仓库。
需要填写Email, Full Name, Username以及password,其中Username与Password后面的步骤需要用到,请记下来,后面需要用到。
注册成功之后创建一个issue
填写完成之后就提交,中间可能你填写的issue会有问题,需要和客服交流一下,最后出现下面的回复说明已经创建成功了。现在你就可以往nexus中上传项目了
发布到Maven仓库中的所有文件都要使用GPG签名,以保障完整性。如果没有GPG前面的项目无法发布到中央仓库,在后面的close阶段会被阻止。
IOS系统请下载GPG Suite:https://gpgtools.org/
Windows系统请下载gpg4win:https://www.gpg4win.org/download.html
安装好了之后你可以通过图形界面生成秘钥,也可以通过命令行生成,图形界面操作简单易懂就不演示了,下面演示命令行:
gpg --gen-key
,此过程会让你输入用户名密码,用户名随便填即可,密码请务必记住,因为后面每次部署发布的时候都会要输入此密码;gpg --list-keys
,下一步需要用到;gpg--keyserver hkp://keyserver.ubuntu.com:11371 --send-keys xxxxxxxxxxxxxxxxxxxx
,假设我的公钥id是xxxxxxxxxxxxxxxxxxxx;gpg --keyserverhkp://pool.sks-keyservers.net --recv-keys xxxxxxxxxxxxxxxxxxxx
,发布成功该步骤完成。在Maven的根目录出去找settings.xml
这个配置文件在apache-maven-3.5.3\conf目录下,打开然后找到servers标签,添加一个服务,这里的id用来唯一标识server,后面配置部署的时候会用到,用户名和密码是你在第一步注册的sonatype账号密码。因为此处填写的是明文,所以请一定注意保管好!被别人拿到了删库跑路都不是问题。
<servers>
<server>
<id>ossid>
<username>Fundebugusername>
<password>passswordpassword>
server>
servers>
我的做法和网上一大堆的教程做法不同就在于这一步,最关键的配置也在这一步。
如果你是一个Maven项目,那么只需要在正在编写的项目中的pom.xml进行配置即可,Maven在打包上传的时候不会把依赖项打包,只会把你的项目代码打包然后上传,这些依赖项都是通过你的pom文件进行记录的,别人引入了你的依赖之后Maven会自动根据你pom的配置进行下载相关包。所以归根结底部署这一步只会把你的项目打包成jar并上传到仓库,依赖项的jar并不会被上传!
如果你是一个纯Java项目,有一些依赖只有class字节码文件或者其他提供的jar包(即你所需的库在Maven仓库中找不到,但是又有相关的字节码文件或jar包),无法将你的项目改为Maven项目,也就是和笔者情况一样,具体操作如下。
<groupId>com.github.tzfungroupId>
<artifactId>vmconsoleartifactId>
<version>1.0.0version>
<name>vmconsolename>
<url>https://github.com/tzfun/VmConsole-Apiurl>
<description>An API that makes it easy to monitor virtual machinesdescription>
<licenses>
<license>
<name>Apache 2name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txturl>
<distribution>repodistribution>
<comments>A business-friendly OSS licensecomments>
license>
licenses>
<scm>
<url>https://github.com/tzfun/VmConsole-Apiurl>
<connection>https://github.com/tzfun/VmConsole-Api.gitconnection>
scm>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<developers>
<developer>
<name>beifengtzname>
<id>beifengtzid>
<email>[email protected]email>
<roles>
<role>Developerrole>
roles>
<timezone>+8timezone>
developer>
developers>
将你的依赖安装到本地仓库:
如果你有一些class字节码文件需要打成jar包,很简单,随便使用一个压缩工具,把你的依赖项目工程压缩成zip格式,注意一定是zip,因为zip压缩格式和jar格式是一样的,打包之后直接把后缀名改成jar即可。
如果你只是一些jar包,没有“散装”的class字节码文件,那么就可以直接进入下一步操作。
用Maven命令行将jar包安装到本地仓库,命令如下:
mvn install:install-file -Dfile=D:\vmconsoel-api.jar -DgroupId=com.github.tzfun -DartifactId=vmconsole-local -Dversion=1.0.0 -Dpackaging=jar
在pom中添加本地仓库依赖
执行成功之后本地仓库就有刚刚那个项目了,接下里把这个依赖添加到pom文件中,这里的groupId、artifactId以及version和上面命令的内容一致。
<dependencies>
<dependency>
<groupId>com.github.tzfungroupId>
<artifactId>vmconsole-localartifactId>
<version>1.0.0version>
dependency>
dependencies>
一般只需要三个插件即可,但是这里我多加了一个assembly插件。如果你本身就是Maven项目,不需要将诸多的依赖打包一起上传(通过pom可以下载依赖,没必要把文件放到仓库),所以不可以不加此插件,将这个插件注释即可。如果你和我情况一样不是Maven项目,那么就需要加入这个插件,它的作用是将所有的依赖jar包合并成一个jar包。
因为这部分内容较多所以我将我的整个pom.xml一起贴出来,不关心此处的读者可以略过看下文。
<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.0modelVersion>
<groupId>com.github.tzfungroupId>
<artifactId>vmconsoleartifactId>
<version>1.0.0version>
<name>vmconsolename>
<url>https://github.com/tzfun/VmConsole-Apiurl>
<description>An API that makes it easy to monitor virtual machinesdescription>
<licenses>
<license>
<name>Apache 2name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txturl>
<distribution>repodistribution>
<comments>A business-friendly OSS licensecomments>
license>
licenses>
<scm>
<url>https://github.com/tzfun/VmConsole-Apiurl>
<connection>https://github.com/tzfun/VmConsole-Api.gitconnection>
scm>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
properties>
<developers>
<developer>
<name>beifengtzname>
<id>beifengtzid>
<email>[email protected]email>
<roles>
<role>Developerrole>
roles>
<timezone>+8timezone>
developer>
developers>
<dependencies>
<dependency>
<groupId>com.github.tzfungroupId>
<artifactId>vmconsole-localartifactId>
<version>1.0.0version>
dependency>
dependencies>
<profiles>
<profile>
<id>releaseid>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-pluginartifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependenciesdescriptorRef>
descriptorRefs>
configuration>
<executions>
<execution>
<id>make-assemblyid>
<phase>packagephase>
<goals>
<goal>singlegoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-source-pluginartifactId>
<version>2.2.1version>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>jar-no-forkgoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-javadoc-pluginartifactId>
<version>2.9.1version>
<executions>
<execution>
<phase>packagephase>
<goals>
<goal>jargoal>
goals>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-gpg-pluginartifactId>
<version>1.6version>
<executions>
<execution>
<phase>verifyphase>
<goals>
<goal>signgoal>
goals>
execution>
executions>
plugin>
plugins>
build>
<distributionManagement>
<snapshotRepository>
<id>ossid>
<url>https://oss.sonatype.org/content/repositories/snapshots/url>
snapshotRepository>
<repository>
<id>ossid>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/url>
repository>
distributionManagement>
profile>
profiles>
project>
接下来在pom.xml目录下执行命令:
mvn clean deploy -P release
其中release不是命令,而是你的pom文件中配置的profile id。在build过程中需要让你输入gpg的密码,输入第2步安装并配置GPG的时候的密码即可。
登录仓库管理网站nexus:https://oss.sonatype.org/#stagingRepositories,这里的用户名密码是第一步sonatype账号密码。
选中你上传的项目,然后先close,等差不多半分钟后如果成功Release按钮就会点亮,再点击Release按钮即可。注意close和Release过程都有相应的校验规则,必须全部符合才能通过,按照上面的步骤操作一般是没有问题的,如果在第4、5部用deploy-file命令来上传jar包那么close过程可能会失败,因为close过程中javadoc、source、gpg三个缺一不可。
如果Release成功之后等待差不多2小时就可以在中央仓库搜到自己的项目啦,地址:https://search.maven.org/
如果你原本就是Maven项目那么仓库提供的依赖代码就可以成功引入了。如果你和我一样从一开始就是非Maven项目,那么你搜索到的依赖确实是你的那个项目,但是引入却不会生效,是因为没有选择classifier,进入你的项目查看项目内容可以看出有几个jar包,你在引入的时候需要选择是哪个,比如我这里就是下面的代码。
<dependency>
<groupId>com.github.tzfungroupId>
<artifactId>vmconsoleartifactId>
<version>1.0.3version>
<classifier>jar-with-dependenciesclassifier>
dependency>
在不了解一个工具运作原理的情况下很难驾驭它,而我这次就是在没有清楚Maven发布流程的情况下就开始东弄西弄,所以浪费了很多时间。在中间我尝试了各种可能的操作,比如deploy-file、反编译整个jar包上传、传到其他私有云(aliyun)、命令行模拟pom等等,最后没办法还是得从了解其运行机制来想办法,笔者详细看了Maven的官方文档然后了解了Maven的几个生命周期,最后再配合其他框架的插件写法才解决了此问题。再次验证了一句话:没有内功基础的剑士练不出好剑法。编程最能体现基础的重要性,理解计算机或语言运作机理才能融汇贯通。
笔者也建立的自己的公众号啦,平时会分享一些编程知识,欢迎各位大佬支持~
扫码或微信搜索北风IT之路关注