Nexus私有maven库部署和使用 - Stars-one
source link: https://www.cnblogs.com/stars-one/p/17047723.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Nexus私有maven库部署和使用
本文为作者原创,允许转载,不过请在文章开头明显处注明链接和出处!!! 谢谢配合~
作者:stars-one
链接:https://www.cnblogs.com/stars-one/p/17047723.html
本篇大约有12003个字,阅读预计需要15.00分钟
原文地址:Nexus私有maven库部署和使用 - Stars-One的杂货小窝
前段圣诞节前后,Jitpack网站突然崩溃了,无法下载依赖,然后过了一个星期才解决了,好在没啥紧急的Android开发任务,没啥影响,但是也给我了一些提醒,可能搭建个私有库会比较保险,于是就是研究了私有库nexus的部署和使用
nexus私有库,支持npm,java,pythod等库的存放,支持的也比较全面,搭建起来也十分简单。
除此之外,还可以拿私有库当一个镜像中转站,比如说阿里云镜像,实际上它也是将一些中央仓库的库都下载保存下来了,以防中央仓库无法访问导致依赖无法下载的问题,有个缺点就是阿里云没有支持Jitpack这种小众网站
我们可以利用私有库,把Jitpack这种网站也加入进来,也提高了下载依赖的速度和环境的配置
1.下载运行
前往官方下载页下载安装文件,这里以window为例,下载了window的压缩包文件
之后解压,得到两个文件夹目录
打开sonatype-work\nexus3\etc\nexus.properties
文件,修改端口号,如下图所示,我是修改为了9888端口(这里需要运行nexus之后,待其安装好相关环境之后才会有这个nexus.properties的文件)
之后进入到nexus-3.45.0-01\bin
命令下,打开cmd窗口,运行命令nexus.exe /run
,即可将nexus运行起来了
运行起来后,我们访问localhost:9888
即可进入到web页面
点击右上角的账号登录,提示我们可以在该路径找到用户名和密码
账号名为admin
,密码则是你用记事本打开那个admin.password
文件里的内容
登录成功后会提示我们输入新密码来修改密码,照着走即可
下一步需要设置是否公开库的选项,不公开的话,下载则需要设置账号和密码才能下载库,我这里就选择了不公开(第二个选项)
之后完成就可以使用了
首先,先介绍说明的对应的仓库信息
maven-releases
发行版组件, hosted 类型maven-snapshots
:快照(调试版本)组件, hosted 类型maven-central
:maven 中央库,就是代理 https://repo1.maven.org/maven2/,proxy 类型maven-public
:仓库分组概念,虚拟的 把上面三个仓库合并形成一个组,方便引用, group 类型
配置maven依赖的时候,我们只需要引用maven-public的地址即可
而我们需要上传组件,可以上传到maven-releases
和maven-snapshots
这两个仓库中即可
原理如下:
Maven中使用
1.手动上传jar包
进入到上传jar包的页面
选择一个jar文件进行上传
然后上传成功,就可以查看到我们的jar包了
2.自动上传jar包
首先,需要maven的setting.xml
文件中配置私服的账号和密码
<server>
<id>myLocalRepo</id>
<username>admin</username>
<password>admin</password>
</server>
PS:注意外层还有个servers标签
之后根据你的需要,在项目里的pom.xml
或setting.xml
中添加配置distributionManagement
标签信息
项目里,则是单独配置;而setting.xml
,则是全局配置的
这里我以项目里为例,在pom.xml中加上配置
<distributionManagement>
<repository>
<id>myLocalRepo</id>
<name>本地私有库</name>
<url>http://localhost:9888/repository/maven-releases/</url>
</repository>
<!-- 配置快照版本的仓库上传地址,这里不演示了,自行修改 -->
<!-- <snapshotRepository>-->
<!-- <id>myLocalRepo</id>-->
<!-- <name>本地私有库</name>-->
<!-- <url>http://localhost:9888/repository/maven-snapshots/</url>-->
<!-- </snapshotRepository>-->
</distributionManagement>
PS:外层还有个project标签,注意id要与上面的serve中的id一致!
这里如果你配置了snapshotRepository
,当你当前的pom文件版本带有snapshot
后缀,就会上传到snapshotRepository
对应的仓库里
使用maven命令进行发布jar包,注意项目路径:
mvn deploy
或者直接点右侧的maven菜单也可以进行
这里需要注意的是,如果你的pom文件里的版本是有snapshot结尾,发布后会jar包会出现在maven-snapshots
仓库中
1.出现405错误
因为仓库用的不是host类型的,所以导致的错误,更换仓库地址即可解决问题
2.上传出现400问题
错误如下提示:
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project mydemo: Failed to deploy artifacts: Could not transfer artifact site.starsone:mydemo:jar:1.0-20230105.091429-1 from/to myLocalRepo (http://localhost:9888/repository/maven-releases/): Transfer failed for http://localhost:9888/repository/maven-releases/site/starsone/mydemo/1.0-SNAPSHOT/mydemo-1.0-20230105.091429-1.jar 400 Repository version policy: RELEASE does not allow version: 1.0-20230105.091429-1
解决方案:
由于当前的pom里面的版本带有关键字snapshots
,而上传的仓库只能接收release版本的,所以导致的错误
将版本的snapshots关键字删除即可解决问题
3.重复发布版本失败
当你发布了一个1.0版本后,然后更改了代码,想重新发布1.0版本,会提示报错
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project mydemo: Failed to deploy artifacts: Could not transfer artifact site.starsone:mydemo:jar:1.0 from/to myLocalRepo (http://localhost:9888/repository/maven-releases/): Transfer failed for http://localhost:9888/repository/maven-releases/site/starsone/mydemo/1.0/mydemo-1.0.jar 400 Repository does not allow updating assets: maven-releases
需要去该仓库里的设置进行以下配置:
4.打包后出现boot-inf文件夹
如果项目中有maven-plugin插件的话,需要配置skip属性为true,否则会出现打包之后出现BOOT-INF,导致引入依赖时没法使用
Gradle中使用
Gradle主要是以上传Android的aar包为例,如果是普通jar包,可以参考官方文档
使用maven-publish'插件:
Gradle7.0版本之后都必须使用这个了,但此插件也支持旧版本的Gradle来使用
单Module发布
这里,假设我们只有一个module,如下图目录所示:
有一个auth的库需要进行发布,我们想要将此库发布在本地私有库中,则需要对其的build.gradle
进行更改,如下面代码(省略了android闭包等部分:
plugins {
id 'com.android.library'
id 'maven-publish'
}
//定义你的私有库地址和密码
def NEXUS_MAVEN_URL = "http://localhost:9888/repository/maven-releases/"
def NEXUS_USERNAME = "admin"
def NEXUS_PASSWORD = "admin"
//对饮的依赖坐标和描述
def POM_NAME = "webviewbase"
def POM_GROUP_ID = "site.starsone"
def POM_ARTIFACT_ID = "webviewbase"
def POM_VERSION = "1.5"
def POM_PACKAGING = "aar"
def POM_DESCRIPTION = "webviewbase基础库"
afterEvaluate {
publishing {
publications {
aar_pub(MavenPublication) {
//定义group和版本
group = POM_GROUP_ID
//定义构造物id
artifactId = POM_ARTIFACT_ID
version = POM_VERSION
pom {
name = POM_NAME
description = POM_DESCRIPTION
url = 'http://www.example.com/library'
//类型设置为aar
packaging = POM_PACKAGING
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'starsone'
name = 'stars-one'
email = '[email protected]'
}
}
}
//带上依赖 ,否则会报错
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
def scopes = [configurations.compile]
if (configurations.hasProperty("api")) {
scopes.add(configurations.api)
}
if (configurations.hasProperty("implementation")) {
scopes.add(configurations.implementation)
}
if (configurations.hasProperty("debugImplementation")) {
scopes.add(configurations.debugImplementation)
}
if (configurations.hasProperty("releaseImplementation")) {
scopes.add(configurations.releaseImplementation)
}
scopes.each { scope ->
scope.allDependencies.each {
if (it instanceof ModuleDependency) {
boolean isTransitive = ((ModuleDependency) it).transitive
if (!isTransitive) {
println "<<<< not transitive dependency: [${it.group}, ${it.name}, ${it.version}]"
return
}
}
if (it.group == "${project.rootProject.name}.libs" || it.version == 'unspecified') {
return
}
if (it.group && it.name && it.version) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', scope.name)
}
}
}
}
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
}
}
repositories {
maven {
//设置仓库地址和账号密码
url = NEXUS_MAVEN_URL
credentials {
username = NEXUS_USERNAME
password = NEXUS_PASSWORD
}
//下面是动态切换release仓库或snapshot仓库
// def releasesRepoUrl = "$buildDir/repos/releases"
// def snapshotsRepoUrl = "$buildDir/repos/snapshots"
// url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
}
编写了上述的脚本代码后,及得resync一下仙姑,之后从右侧的Gradle菜单进入到你的模块下,展开task目录,可以找到发布的命令,如下图所示
这里发布的话,步骤有4个:
- 修改版本号(上述脚本里的
POM_VERSION
字段) - 执行clean命令
- 执行编译命令
- 执行发布命令
具体步骤如下图所示:
gradle如何依赖私有库的话,请看下面的章节说明
多Module发布
如果我们是想要发布多个Module,如果采用上述的方法,就是得在每个Module里都加上脚本,十分繁琐。
研究了下,想实现Jitpack那种可以一键发布所有Module的方法,最终还是不成功,于是就采用了一种稍微折中的方法,就是创建一个公共的gradle脚本,用来发布aar,然后所有的Module去引用此脚本即可,虽然也要对每个Module进行修改,但也算是比较折中的方法了,图省事的话可以用替换功能进行脚本的添加
公共脚本nexus-maven-publish.gradle
,放在了项目的根目录,与setting.gradle
同级别,脚本代码如下:
apply plugin: 'maven-publish'
def NEXUS_MAVEN_URL = "http://localhost:9888/repository/maven-releases/"
def NEXUS_USERNAME = "admin"
def NEXUS_PASSWORD = "admin"
//与jitpack发布的保持同个组织名
def POM_GROUP_ID = "com.github.TYKYTeam.swan-android-libray"
//版本好
def POM_VERSION = "2.1"
//aar包方式
def POM_PACKAGING = "aar"
//下面三个数值自动读取模块名
def POM_NAME = ""
def POM_ARTIFACT_ID = ""
def POM_DESCRIPTION = ""
def depList = parent.getDependencies()
depList.getModules().each {
println "数据。。" + this.name
POM_ARTIFACT_ID = this.name
POM_NAME = this.name
}
afterEvaluate {
publishing {
publications {
aar_pub(MavenPublication) {
//定义group和版本
group = POM_GROUP_ID
//定义构造物id
artifactId = POM_ARTIFACT_ID
version = POM_VERSION
// artifact androidSourcesJar//将源码打包进aar,如果不需要可以去掉
// artifact androidJavadocsJar//将注释打包进aar,如果不需要可以去掉
artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
pom {
name = POM_NAME
description = POM_DESCRIPTION
url = 'http://www.example.com/library'
//类型设置为aar
packaging = POM_PACKAGING
licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id = 'com'
name = 'stars-one'
email = '[email protected]'
}
}
}
//带上依赖 ,否则会报错
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
def scopes = [configurations.compile]
if (configurations.hasProperty("api")) {
scopes.add(configurations.api)
}
if (configurations.hasProperty("implementation")) {
scopes.add(configurations.implementation)
}
if (configurations.hasProperty("debugImplementation")) {
scopes.add(configurations.debugImplementation)
}
if (configurations.hasProperty("releaseImplementation")) {
scopes.add(configurations.releaseImplementation)
}
scopes.each { scope ->
scope.allDependencies.each {
if (it instanceof ModuleDependency) {
boolean isTransitive = ((ModuleDependency) it).transitive
if (!isTransitive) {
println "<<<< not transitive dependency: [${it.group}, ${it.name}, ${it.version}]"
return
}
}
if (it.group == "${project.rootProject.name}.libs" || it.version == 'unspecified') {
return
}
if (it.group && it.name && it.version) {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
dependencyNode.appendNode('scope', scope.name)
}
}
}
}
}
}
repositories {
maven {
//设置仓库地址和账号密码
url = NEXUS_MAVEN_URL
credentials {
username = NEXUS_USERNAME
password = NEXUS_PASSWORD
}
//下面是动态切换release仓库或snapshot仓库
// def releasesRepoUrl = "$buildDir/repos/releases"
// def snapshotsRepoUrl = "$buildDir/repos/snapshots"
// url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
}
}
}
}
在Module里build.gradle
文件里进行引用:
buildscript {
apply from: "../nexus-maven-publish.gradle"
}
plugins {
id 'com.android.library'
id 'com.github.dcendents.android-maven'
}
//后面的省略...
PS:buildscript要放在plugins之前
发布aar的步骤:
1.修改nexus-maven-publish.gradle
文件里定义的版本号POM_VERSION
注意下面的步骤执行的命令不是单个Module里的哦!!
2.清除数据和重新编译
3.发布(注意和上面的单Module有所不同)
本来想着自定义一个Task,实现上面的各命令的点击操作的,不然每次发布都要点个几次鼠标可太累了,但最终还是实现不了,如果有大佬路过可以在评论区指点一下,感激不尽
使用maven插件:
plugins {
id 'com.android.library'
id 'publishing'
id 'maven'
}
def NEXUS_MAVEN_URL = "http://localhost:9888/repository/maven-releases/"
def NEXUS_USERNAME = "admin"
def NEXUS_PASSWORD = "admin"
def POM_NAME = "webviewbase"
def POM_GROUP_ID = "site.starsone"
def POM_ARTIFACT_ID = "webviewbase"
def POM_VERSION = "1.0"
def POM_PACKAGING = "aar"
def POM_DESCRIPTION = "webviewbase基础库"
uploadArchives {
configuration = configurations.archives
repositories {
mavenDeployer {
repository(url: NEXUS_MAVEN_URL) {
authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
}
// snapshotRepository(url: NEXUS_MAVEN_SNAPSHOT_URL) {
// authentication(userName: NEXUS_USERNAME, password: NEXUS_PASSWORD)
// }
//'groupId:artifactId:version' 或 'groudId:artifactId:version@aar' 形式
pom.project {
name POM_NAME
groupId POM_GROUP_ID
artifactId POM_ARTIFACT_ID
version POM_VERSION
packaging POM_PACKAGING
description POM_DESCRIPTION
}
}
}
}
// 生成sources.jar 写 artifacts {} 之前
task androidSourcesJar(type: Jar) {
classifier = 'sources'
from android.sourceSets.main.java.srcDirs
}
artifacts {
//编译的源码类型
archives androidSourcesJar
//archives androidJavadocsJar
}
android{
...
}
通过右侧的gradle菜单可以触发上传
依赖本地私有库(Maven)
步骤稍微有些繁琐,需要修改maven目录下的setting.xml
文件,不过改一次就好
1.serve配置
首先声明一下私有库的账号密码
注意这里的id是随意定义的,可以自由编写,但需要与下面的profile里的id对应
<server>
<id>localRepo</id>
<username>admin</username>
<password>admin</password>
</server>
这里看网上的介绍说,只是打包上传的时候maven会读取这里,实际上,如果私有库没有开放允许任何人访问(即我上面部署操作的步骤),到时候依赖的时候也会去根据id去读取这个server标签,否则到时候也是无法依赖的
2.profile配置
网上看其他资料,是去加了mirror,但实际上:
如果mirrors下即使有多个mirror配置,实际上只会去第一个mirror里找,找不到不会往下个mirror里找的
除非第一个mirror因为网络原因链接不上,才会触发到下一个mirror里去找依赖的操作逻辑
<profile>
<id>localRepoProfile</id>
<activation>
<jdk>1.8</jdk>
</activation>
<repositories>
<repository>
<id>localRepo</id>
<name>本地私有库</name>
<url>http://localhost:9888/repository/maven-public/</url>
<layout>default</layout>
<snapshotPolicy>always</snapshotPolicy>
</repository>
</repositories>
</profile>
3.激活配置
<activeProfiles>
<activeProfile>localRepoProfile</activeProfile>
</activeProfiles>
之后在pom.xml里输入本地私有库里的依赖坐标即可正常依赖
补充-单独设置项目使用私有库
上面的2和3步骤,是在全局的maven中进行配置的个更改,而还有可以单独为某个项目去配置的,直接去修改pom.xml文件即可,如下面例子:
<project>
...
<repositories>
<repository>
<id>localRepo</id>
<name>本地私有库</name>
<url>http://localhost:9888/repository/maven-public/</url>
</repository>
</repositories>
</project>
依赖本地私有库(Gradle)
如果私有库是开了账号限制,可以在依赖的仓库源中设置账号和密码
maven{
url 'http://xxxx:8082/artifactory/android_group'
//下面这是账号和密码
credentials{
username=""
password = ""
}
}
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK