Nexus私有maven库部署和使用
原文地址: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运行起来了
2.登录
运行起来后,我们访问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 = 'stars-one@example.com'
}
}
}
//带上依赖 ,否则会报错
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 = 'stars-one@example.com'
}
}
}
//带上依赖 ,否则会报错
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 = ""
}
}
参考
- 使用 Sonatype Nexus 3 搭建 Maven 私服、本地私有 Maven 仓库,Gradle 打包 jar 、aar 后自动上传到 Nexus Maven 仓库配置_路易斯睿齐的博客-CSDN博客_sonatype/nexus3
- 用Nexus搭建Maven私服 - 掘金
- Maven配置私有仓库 - 阿尔法哲 - 博客园
- Maven使用多种方式配置私有仓库 - 简书
- 【maven】超详细Maven搭建私库、上传jar包和使用_I am Walker的博客-CSDN博客_私库active
- Maven进阶-配置私服(Nexus 的使用)_槐阳7的博客-CSDN博客_nexus 修改端口
- 【Android Studio Gradle】发布aar到私有Artifactory仓库_梦否的博客-CSDN博客_android studio 添加aar
- Gradle用户手册
- Gradle | Releases各版本的用户手册
- 使用Gradle发布工件到Maven仓库_精装机械师的博客-CSDN博客_gradle发布到仓库
Nexus私有maven库部署和使用的更多相关文章
- 搭建私有maven库发布及使用流程
一:背景 Apache Maven是当Java技术栈前最流行的项目管理工具,它提供了一系列方便快捷的命令帮助程序员们进行Java工程的开发工作.Maven服务器位于美国,由于出国带宽和众多因素,在国内 ...
- 私有maven库发布及使用流程
## 私有maven库发布流程 ### 环境配置 - idea环境下,如果使用内置maven,需要手动生成settings.xml,并关联. - 操作如下 - 生成settings.xml 右键pom ...
- 创建私有maven库
在公司搭建私有maven库,我为了在本机做测试,我选择Sonatype nexus oss,在docker里面安装 1.Mac上安装docker 下载地址:https://github.com/boo ...
- nexus 私有 maven 仓库的搭建
下载地址 页面 : https://help.sonatype.com/repomanager3/download 首先需要安装jdk .安装棒法我 前面的文章有写.https://www.cnblo ...
- linux下安装nexus repository及Intellij Idea集成私有maven
前段日子公司搞java项目,使用nexus repository搭建了私有maven库,现在把原来的私有nuget也迁到nexus repository上了,下面介绍下搭建流程: https://he ...
- 私有Maven仓库安装和使用
安装 这里选择安装的是windows平台,linux安装类似,下载可能要梯子 官网下载页 https://help.sonatype.com/repomanager2/download 下载链接 ht ...
- nexus搭建maven私服及私服jar包上传和下载
nexus搭建maven私服及私服jar包上传和下载 标签: nexus管理maven库snapshot 2017-06-28 13:02 844人阅读 评论(0) 收藏 举报 分类: Maven(1 ...
- CentOS安装Nexus(Maven私有库)详细配置及上传本地jar到私服
Nexus原理 Maven的原理就是将jar从远程中央仓库下载到PC磁盘的本地仓库,当本地仓库没有发现需要的jar就会去Maven默认的远程中央仓库Maven Central(由Apache维护)中寻 ...
- Android业务组件化之Gradle和Sonatype Nexus搭建私有maven仓库
前言: 公司的业务组件化推进的已经差不多三四个月的时间了,各个业务组件之间的解耦工作已经基本完成,各个业务组件以module的形式存在项目中,然后项目依赖本地的module,多少有点不太利于项目的并行 ...
- 使用nexus创建maven私有仓库
nexus安装 nexus下载 wget https://sonatype-download.global.ssl.fastly.net/nexus/oss/nexus-2.11.1-01-bundl ...
随机推荐
- Java并发编程 | Synchronized原理与使用
Java提供了多种机制实现多线程之间有需要同步执行的场景需求.其中最基本的是Synchronized ,实现上使用对象监视器( Monitor ). Java中的每个对象都是与线程可以锁定或解锁的对象 ...
- Java8新特性—四大内置函数式接口
Java8新特性--四大内置函数式接口 预备知识 背景 Lambda 的设计者们为了让现有的功能与 Lambda 表达式良好兼容,考虑了很多方法,于是产生了函数接口这个概念. 什么是函数式接口? 函数 ...
- 【笔记】入门DP(Ⅱ)
0X00 P1433 吃奶酪 状压 \(DP\),把经过的点压缩成01串.若第 \(i\) 位为 \(0\) 表示未到达,为 \(1\) 则表示已到达. 用 \(f[i][j]\) 表示以 \(i\) ...
- Codeforces Round #817 (Div. 4)
CF传送门 因为洛谷题库未更新,所以给出的题面都是CF的. 现场打真是太卡了(梯子挂了,codeforc.es也崩了),所以五六分钟才打开题目 \(qwq\) A. Spell Check 萌萌题,把 ...
- C#与Halcon联合编程之用PictureBox控件替代HWindowControl控件
在使用HALCON和C#联合编程,有时候要使用halcon的HWindowControl控件,但是我发现,HWindowControl的图片显示控件,不能使用GDI+绘制ROI,不知道为什么,反正我测 ...
- 8.drf-序列化器
在序列化类中,如果想使用request,则可以通过self.context['request']获取 序列化器的主要由两大功能 - 对请求的数据进行校验(底层调用的是Django的Form和Model ...
- 渗透测试中遇到的Adminer任意文件读取漏洞
渗透测试中遇到的Adminer任意文件读取漏洞 免责声明: 软件简介 漏洞原理 漏洞复现 字典脚本 直接输入文件读取脚本 直接输入文件绝对路径读取脚本使用方法 字典脚本使用方法 免责声明: 免责声明: ...
- 使用 JWT 生成 token
JWT 简介 JWT:Json Web Token 官网:https://jwt.io 优点:可生成安全性较高的 token 且可以完成时效性的检验(登陆过期检查) JWT 结构:(由官网获取) JW ...
- kubeedge架构与核心设计---https://bbs.huaweicloud.com/webinar/100009
今天是kubeedge的第一节课,今天主要带大家回顾一下云原生和边缘计算的发展历程 然后我们会重点介绍一下kubeedge这个项目,他的设计背景和核心理念与我们整体的架构 首先是我们来简单回归一下云原 ...
- layui的button失效、layui绑定失效
内容呢,就一句话. 因为不会报错,所以这个坑,找了半天......淦 button失效直接提交刷新可能是没加lay-submit 属性. <button class="layui-bt ...