mvn 命令上传文件到 Maven 仓库

针对一个 Maven 的 Java 项目,我们执行 mvn deploy 命令时想要把生成的 jar 包上传到 Maven 仓库(本文将使用私有的 Nexus 仓库)中去。所要用到的插件 Maven Deploy Plugin,本文实际就是讲述如何用该插件上传 jar 包到 Maven  仓库,更多用法请参考该插件的官方文档。

本文关键性的两个配置文件是 pom.xml 和 settings.xml。前者配置仓库的地址,后者中配置用户名和密码。要确定 Maven 使用了哪个 settings.xml 文件,用 mvn -X 查看,比如下面的输出

[DEBUG] Reading global settings from /usr/local/Cellar/maven/3.8.3/libexec/conf/settings.xml
[DEBUG] Reading user settings from /Users/yanbin/.m2/settings.xml

Maven 还允许在执行 mvn 命令时用  -s 或 --settings 参数指定 settings.xml 文件,如 mvn deploy --settings setting.xml

所以对于 settings.xml 文件的修改,可修改全局的,用户的或参数 --settings 指定的。

来一个实际的应用场景,假如我们要上传 jar 包(根据是否为 SNAPSHOT 包) 到下方相应的仓库中

  1. https://nexus.example.com/repository/maven-releases: release 包,即版本号不是 *-SNAPSHOT
  2. https://nexus.example.com/repository/maven-snapshots: snapshot 包,即版本号为 *-SNAPSHOT

瞧瞧可采用的几种方式

基本的操作方式

下面是一个完整的 pom.xml 文件

由于 version 是 1.0.0-SNAPSHOT,所以将会部署到 distributionManagement/snapshotRepository 指示的仓库中,该仓库的 id 是 private-snapshot。如果我们执行 mvn deploy,Maven 将从 settings.xml 中找到该 id 对应的用户名和密码。因此我们须在 setting.xml 文件中预先配置

假如我们修改用户的 settings.xml 文件 ~/.m2/setting.xml

现在我们来执行 mvn deploy, 这里跳过 test 和 install 这两步

上传成功了,如果 version 不是 *-SNAPSHOT, 比如为 1.0.0, 它将会上传到 id 为  private-release 仓库,在 ~/.m2/settings.xml 就要有对应 id 为 private-release<server> 来配置用户和密码。

还可以其他多种传入用户名密码的方式

通过系统属性传入帐号信息

配置 ~/.m2/settings.xml 的 <server>

mvn 命令为

$ mvn deploy -DCI_USERNAME=admin -DCI_PASSWORD=admin123

通过环境变量传入帐号信息

配置 ~/.m2/settings.xml 的 <server>

执行 mvn 命令前必须设置相应的环境变量

$ export CI_USERNAME=admin
$ export CI_PASSWORD=admin123
$ mvn deploy

settings.xml 中全动态

我们还可以在 settings.xml 把 <server> 的 id, username 和 password 配置成全动态的,如

有了它以后就能以一变应万变,只要看着 pom.xml 中的 distributionManagement/*/id 下菜就行了,如

$ mvn deploy -Drepo.id=private-snapshot -Drepo.login=admin -Drepo.pwd=admin123

这种全动态的 <server> 配置放到  settings.xml 中简直是百利而无一害,就是一个万能的 <server> 配置

配置用户名密码到 url 中

这种方式我们用不着 settings.xml 文件,测试前可把  settings.xml 文件删除。只需修改 pom.xml 文件, 给 distributionManagement 中的 <url> 中配置上用户名和密码

然后执行 mvn deploy 即能成功上传 jar 包。这种配置方式肯定不安全,绝对不应该把密码放到项目文件中去的,所以千万别采用。

使用 alt*Repository 系统属性

继续往深处挖,mvn deploy:deploy 还提供对 altDeploymentRepository, altSnapshotDeploymentRepository, 和 altReleaseDeploymentRepository 三个属性的覆盖。这就能演绎出更精致的用法。在 pom.xml 中整个 <distributionManagement> 都不需要配置,你不想要 settings.xml 文件也没问题,只要命令

$ mvn deploy -DaltDeploymentRepository=private-snapshot::default::http://admin:admin123@nexus.example.com/repository/maven-snapshots

如果是搭配前面那个万能的 settings.xml <server> 配置,需要命令就是

$ mvn deploy -DaltDeploymentRepository=private-snapshot::default::http://nexus.example.com/repository/maven-snapshots \
  -Drepo.id=private-snapshot -Drepo.login=admin -Drepo.pwd=admin123

注意 alt*Repository 的格式是 id::layout::url, layout 为 default 就行。其他两个,altSnapshotDeploymentRepository 和  altReleaseDeploymentRepository  也能用系统属性覆盖。

-DaltDeploymentRepository 的方式给我们带来一种不用修改原有的 pom.xml 文件也能把它部署到任意仓库的便利。如果是自己管理的 Maven 项目,还是推荐在  pom.xml 中加上 <distributionManagement> 配置,这为我们使用 mvn deploy 命令更简单。

直接上传一个 jar 文件

有时候拿到的是一个别人的 jar,没有源文件,想把它直接上传到 Maven 仓库中去供其它 Java 项目享用, 这时候我们要用到的命令是 mvn deploy:deploy-file。当然登陆 nexus Web 控制台手工上传也行,本文主要讲 mvn deploy 的使用。

回顾一下用 twine 把一个 Python 的 whl 包上传到 nexus 上的方式

twine upload --repository-url=https://nexus.example.com/repository/pypi-hosted/ dist/bounded_executor-0.0.3-py3-none-any.whl

直接上传一个 jar 文件与针对 Maven 项目执行 mvn deploy 并无多大区别,唯一不同的是 Maven 项目有一个 pom.xml 文件,在其中有 groupId, artifactId, version 等的描述,而使用 mvn deploy:deploy-file 的话就要在命令中给出相同的信息。mvn deploy:deploy-file 也能用 -DpomFile 指定一个 pom.xml 文件, 如果该 jar 有传递的依赖也许是有必要用这个参数。

应用 settings.xml 的帐号信息

执行 deploy:deploy-file 依旧可以用 settings.xml 文件,配置方式与前面三种方式是一样的,帐户信息可明文配置,或从系统属性或环境变量中来。假如 jar 包文件名是 redis-common-1.0.0-SNAPSHOT.jar, ~/.m2/settings.xml 中配置的 server

上传该 jar 包到私有仓库的命令是

mvn deploy:deploy-file -DCI_USERNAME=admin -DCI_PASSWORD=admin123 \
  -DgroupId=blog.yanbin.redis -DartifactId=redis-common -Dversion=1.0.0-SNAPSHOT -Dpackaing=jar \
  -DrepositoryId=private-snapshot \
  -Durl=http://nexus.example.com/repository/maven-snapshots \
  -Dfile=redis-common-1.0.0-SNAPSHOT.jar

settings.xml 中配置 <server> 的 id, username, password 全部从系统属性/环境变量中来的方式也适用于此处

无需 settings.xml 文件

也可以完全不用 settings.xml 文件,而在 mvn 命令中的 URL 中带上用户名和密码。测试下面的命令前把 ~/.m2/settings.xml 文件先删除

mvn deploy:deploy-file \
  -DgroupId=blog.yanbin.redis -DartifactId=redis-common -Dversion=1.0.0-SNAPSHOT -Dpackaing=jar \
  -Durl=http://admin:admin123@nexus.example.com/repository/maven-snapshots \
  -Dfile=redis-common-1.0.0-SNAPSHOT.jar

这种方式对于临时把一个 jar 包上传到私有仓库更快捷,反正是本机执行,不应有什么安全隐患。此时如果使用 settings.xml 配置了用户名和密码,那么 -Durl 中的用户名和密码将被忽略。

和任何 bash 命令一样,密码中带有特殊符号的要注意转义,比如密码是 aB!ak47%^,在 mvn deploy:deploy-file 命令的 -Durl 写成

-Durl=http://admin:aB!ak47%^@nexus.example.com/repository/maven-snapshots

在 zsh 中将会看到

zsh: event not found: ak47

在 bash 中看到的是

bash: !ak47%^@nexus.example.com/repository/maven-snapshots: event not found

原因是感叹号 ! 在 zsh 和 bash 中是唤起一个历史命令,如 !ak47 是从历史命令中查找一个以 ak47 开头的命令,没有的话就是 event not found.

所以我们必须对感叹号进行转义,在它前头加上反斜杠,完整的 mvn deploy:deploy-file 命令是

mvn deploy:deploy-file \
  -DgroupId=blog.yanbin.redis -DartifactId=redis-common -Dversion=1.0.0-SNAPSHOT -Dpackaing=jar \
  -Durl=http://admin:aB\!ak47%^@nexus.example.com/repository/maven-snapshots \
  -Dfile=redis-common-1.0.0-SNAPSHOT.jar

实际的密码  aB!ak47%^ 被转义为 aB\!ak47%^

如果把这个 mvn deploy:deploy-file 命令写到一个 deploy.sh 文件中的话,转义又多余了,其中 -Durl 部分写成 -Durl=http://admin:aB!ak47%^@nexus.... ,然后用  sh deploy.sh 执行也不会有问题。

Maven effective-settings 插件

该插件能显示出 Maven  用到的 settings 信息,包括其中配置的用户名密码

$ mvn help:effective-settings -DshowPasswords=true

总结

对于 mvn deploy 或 mvn deploy:deploy-file 命令,所需要的用户名密码信息可配置到本地的 settings.xml 文件中。

如果想通过命令行传递帐号信息,在 settings.xml 加上一个全能的 <server> 配置

是非常有积极意义的,在 CI(如 Jenkins) 上执行时要注意屏蔽控制台输出中的密码信息。

使用 -DaltDeploymentRepository=<id::default::user:pass@url> 的方式能够在不触及任何配置的情况下把构建部署到任意仓库中

最后又要重复一下,真正要把 mvn deploy 用法写下来,不可避免的会越走越远,这就是写博客的意义,与草草了事的笔记不在一个数量极上。

链接:

  1. Maven Deploy to Nexus
  2. Maven: Deploy Artifacts to Nexus
  3. Guid to deploying 3rd party JARs to remote repository
  4. Is it possible to pass a password in Maven Deploy in the command line?

类别: Java/JEE. 标签: , . 阅读(23). 订阅评论. TrackBack.
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x