文章目录
- 3. 进阶
- 3.1 maven依赖
- 传递特性
- 3.2 依赖冲突
- 3.2.1 自动选择原则
- 3.2.2 手动排除
- 3.3 聚合工程
- 3.3.1 继承
- 介绍
- 继承作用
- 继承语法
- 父工程依赖统一管理-dependencyManagement
- 3.3.2 工程聚合关系
- 简介
- 聚合作用
- 聚合作用
- 3.4 私服
- 3.4.1 简介
- 3.4.2 Nexus下载安装
- Nexus3
- Nexus2
- 3.4.3 修改仓库
- 3.4.4 通过Nexus下载jar包
- 3.4.5 把jar包部署到Nexus中
- 3.4.6 引用别人部署的 jar 包
3. 进阶
3.1 maven依赖
传递特性
假如有Maven项目A,项目B依赖A
,项目C依赖B
。那么我们可以说 C依赖A
。也就是说,依赖的关系为:C—>B—>A
, 那么我们执行项目C时,会自动把B、A都下载导入到C项目的jar包文件夹中,这就是依赖的传递性。
依赖传递的好处/作用
- 简化依赖导入过程
- 确保依赖版本正确
案例
-
在
A
依赖B
,B
依赖C
的前提下,C
是否能够传递到A
,取决于B
依赖C
时使用的依赖范围以及配置 -
B
依赖C
时使用compile
范围:可以传递 -
B
依赖C
时使用 test 或provided
范围:不能传递,所以需要这样的 jar 包时,就必须在需要的地方明确配置依赖才可以。 -
B 依赖 C 时,若配置了以下标签,则不能传递。
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.15</version><optional>true</optional> </dependency>
依赖传递终止
- 非compile范围进行依赖传递
- 使用optional配置终止传递
- 依赖冲突(传递的依赖已经存在)
3.2 依赖冲突
maven自动解决依赖冲突问题能力,会按照自己的原则,进行重复依赖选择。同时也提供了手动解决的冲突的方式,不过不推荐!
解决依赖冲突(如何选择重复依赖)方式:
- 自动选择原则
- 手动排除
3.2.1 自动选择原则
短路优先原则(第一原则)
A—>B—>C—>D—>E—>X(version 0.0.1)
A—>F—>X(version 0.0.2)
则A依赖于X(version 0.0.2)。
依赖路径长度相同情况下,则“先声明优先”(第二原则)
A—>E—>X(version 0.0.1)
A—>F—>X(version 0.0.2)
在<depencies></depencies>
中,先声明的,路径相同,会优先选择
3.2.2 手动排除
<dependency><groupId>com.atguigu.maven</groupId><artifactId>pro01-maven-java</artifactId><version>1.0-SNAPSHOT</version><scope>compile</scope><!-- 使用excludes标签配置依赖的排除 --><exclusions><!-- 在exclude标签中配置一个具体的排除 --><exclusion><!-- 指定要排除的依赖的坐标(不需要写version) --><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions>
</dependency>
3.3 聚合工程
3.3.1 继承
介绍
Maven 继承是指在 Maven 的项目中,让一个项目从另一个项目中继承配置信息的机制。继承可以让我们在多个项目中共享同一配置信息,简化项目的管理和维护工作。
继承作用
在父工程中统一管理项目中的依赖信息。
它的背景是:
- 对一个比较大型的项目进行了模块拆分。
- 一个 project 下面,创建了很多个 module。
- 每一个 module 都需要配置自己的依赖信息。
它背后的需求是:
- 在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理。
- 使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一。
- 使用框架时所需要的 jar 包组合(或者说依赖信息组合)需要经过长期摸索和反复调试,最终确定一个可用组合。这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索。
通过在父工程中为整个项目维护依赖信息的组合既保证了整个项目使用规范、准确的 jar 包;又能够将以往的经验沉淀下来,节约时间和精力。
继承语法
父工程(父工程无须写 java 代码,因此 src 删除,只留下 pom.xml 即可)
<groupId>com.atguigu.maven</groupId>
<artifactId>pro03-maven-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom -->
<packaging>pom</packaging>
子工程(子工程在父工程下去创建,会发现子工程的 pom.xml 中多了一个 parent 标签)
<!-- 使用parent标签指定当前工程的父工程 -->
<parent><!-- 父工程的坐标 --><groupId>com.atguigu.maven</groupId><artifactId>pro03-maven-parent</artifactId><version>1.0-SNAPSHOT</version>
</parent><!-- 子工程的坐标 -->
<!-- 如果子工程坐标中的groupId和version与父工程一致,那么可以省略 -->
<!-- <groupId>com.atguigu.maven</groupId> -->
<artifactId>pro04-maven-module</artifactId>
<!-- <version>1.0-SNAPSHOT</version> -->
父工程中使用 dependences 标签后,集成的依赖都会无条件的继承给子工程
父工程依赖统一管理-dependencyManagement
父工程声明版本(在 dependencyManagement 标签中再建立 dependencies 标签,这样父工程中的依赖就不会直接继承给子工程)
<!-- 使用dependencyManagement标签配置对依赖的管理 -->
<!-- 被管理的依赖并没有真正被引入到工程 -->
<dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>6.0.10</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>6.0.10</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.0.10</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>6.0.10</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>6.0.10</version></dependency></dependencies>
</dependencyManagement>
子工程引用版本(此时在子工程的 dependencies 标签中添加需要依赖的坐标,不许 version 标签,自动继承父工程的版本)
<!-- 子工程引用父工程中的依赖信息时,可以把版本号去掉。 -->
<!-- 把版本号去掉就表示子工程中这个依赖的版本由父工程决定。 -->
<!-- 具体来说是由父工程的dependencyManagement来决定。 -->
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId></dependency>
</dependencies>
3.3.2 工程聚合关系
简介
Maven 聚合是指将多个项目组织到一个父级项目中,以便一起构建和管理的机制。聚合可以帮助我们更好地管理一组相关的子项目,同时简化它们的构建和部署过程。
聚合作用
- 管理多个子项目:通过聚合,可以将多个子项目组织在一起,方便管理和维护。
- 构建和发布一组相关的项目:通过聚合,可以在一个命令中构建和发布多个相关的项目,简化了部署和维护工作。
- 优化构建顺序:通过聚合,可以对多个项目进行顺序控制,避免出现构建依赖混乱导致构建失败的情况。
- 统一管理依赖项:通过聚合,可以在父项目中管理公共依赖项和插件,避免重复定义。
聚合语法
父项目中包含的子项目列表(对 modules 标签进行标记,实际上在创建子工程的时候,会自动生成 module 标签的内容)
<project><groupId>com.example</groupId><artifactId>parent-project</artifactId><packaging>pom</packaging><version>1.0.0</version><modules><module>child-project1</module> <!-- 这中间是工程的路径,而不是工程名--><module>child-project2</module></modules>
</project>
聚合作用
通过触发父工程构建命令、引发所有子模块构建!产生反应堆!
当对父工程进行操作时,子工程会进行同样的操作,比如 clean 父工程,子工程也 clean
父工程进行 package 操作,子工程也进行了 package 打包
3.4 私服
3.4.1 简介
Maven 私服是一种特殊的Maven远程仓库,它是架设在局域网内的仓库服务,用来代理位于外部的远程仓库(中
央仓库、其他远程公共仓库)。
当然也并不是说私服只能建立在局域网,也有很多公司会直接把私服部署到公网,具体还是得看公司业务的
性质是否是保密的等等,因为局域网的话只能在公司用,部署到公网的话员工在家里也可以办公使用。
建立了 Maven 私服后,当局域网内的用户需要某个构件时,会按照如下顺序进行请求和下载。
- 请求本地仓库,若本地仓库不存在所需构件,则跳转到第2步;
- 请求 Maven 私服,将所需构件下载到本地仓库,若私服中不存在所需构件,则跳转到第3步。
- 请求外部的远程仓库,将所需构件下载并缓存到 Maven 私服,若外部远程仓库不存在所需构件,则 Maven 直接报错。
此外,一些无法从外部仓库下载到的构件,也能从本地上传到私服供其他人使用。
优势
-
节省外网带宽
消除对外部远程仓库的大量重复请求(会消耗很大量的带宽),降低外网带宽压力。
-
下载速度更快
Maven私服位于局域网内,从私服下载构建更快更稳定。
-
便于部署第三方构件
有些构件无法从任何一个远程仓库中获得(如:公司或组织内部的私有构件、Oracle的JDBC驱动等),建立
私服之后,就可以将这些构件部署到私服中,供内部Maven项目使用。 -
提高项目的稳定性,增强对项目的控制
如果不建立私服,那么Maven项目的构件就高度依赖外部的远程仓库,若外部网络不稳定,则项目的构建过
程也会变得不稳定。建立私服后,即使外部网络状况不佳甚至中断,只要私服中已经缓存了所需的构件,Maven也能够正常运行。
私服软件(如:Nexus)提供了很多控制功能(如:权限管理、RELEASE/SNAPSHOT版本控制等),可以对仓库进行一些更加高级的控制。
-
降低中央仓库得负荷压力
由于私服会缓存中央仓库得构件,避免了很多对中央仓库的重复下载,降低了中央仓库的负荷
常见的Maven私服产品
- Apache的Archiva
- jFrog的Artifactory
- Sonatype的Nexus(['nekses])(当前最流行、使用最广泛)
3.4.2 Nexus下载安装
目前Nexus 分为 Nexus 2.x 和 Nexus 3.x 两个大版本,在以往框架,有了3.x一定不会再更新2.x了,会继续向上延续3.x,4.x,而Nexus对于这两个版本是并行的关系。也就是2.x在更新迭代,3.x也在更新迭代,两个大的版本互不影响!两个版本连ui界面都不一样,但是其功能是一样的。
Nexus3
Download Nexus Repository OSS | Sonatype
打开之后可能会让你输入一些信息,正常输入即可,输入过后会跳转到该页面:
这只是一个广告页,其实还在刷新。
刷完之后就是一个下载链接,可能浏览器根本打不开,直接复制这个链接到迅雷即可下载。可能有的版本迅雷都下载不了,这时候可以选择降低下载链接当中的下载版本,然后继续拿迅雷下载。
将下载 Nexus 安装包解压到本地磁盘,可获得 nexus-3.49.0-02 和 sonatype-work 2 个目录,如下图。
其中:
- nexus-3.49.0-02:该目录中包含了 Nexus 3.x 运行所需要的文件,如启动脚本、依赖 jar 包等。
- sonatype-work:该目录中包含了 Nexus 3.x 生成的配置文件、日志文件等。
打开nexus-3.49.0-02/bin 目录,其中nexus.exe就是运行的。当然无法直接点击启动,需要通过命令将服务安装后再进行运行。
使用管理员运行cmd:
按 Windows 键 + X.然后选择windows powershell 管理员
- 安装服务:nexus.exe /install
- 启动服务:nexus.exe /start
- 带控制台的启动服务:nexus.exe /run
- 停止服务:nexus.exe /stop
- 卸载服务:nexus.exe /uninstall
- 安装好后在服务当中可以查看自己的nexus服务
运行一下命令nexus.exe /run
出现一下结果或说明启动成功
如果启动失败的话,删除重新解压就可以了。
启动后访问(启动可能会有点慢,多等一会就可以了):http://localhost:8081/
页面长这个样子
点击登录sign in
-
初始账号是:admin
-
初始密码在:
sonatype-work\nexus3\admin.password
中(登录进去会提示让你更改密码的)进来可能会提示你让你改密码,正常改就可以:
紧接着还会提示你这个是否允许匿名访问,这里我建议选择否:
登录之后的界面:
在etc目录下有个nexus-default.properties可以配置端口号
Nexus2
https://help.sonatype.com/en/download-nexus-2.html
https://help.sonatype.com/en/download.html
2.x的bin目录中不是exe,如下图。
进入 \nexus-2.15.1-02\bin\jsw 文件夹,根须操作系统版本选择合适的目录,由于我的操作系统是 Windows 10 64 位,所以我选择 windows-x86-64 目录,如下图所示。
进入 windows-x86-64 目录后可以看到如下文件。
其中:
console-nexus.bat:启动 Nexus 并在 DOS 命令行中展示启动过程。
install-nexus.bat:将 Nexus 安装为 Windows 服务,开机自动启动。
start-nexus.bat:启动 Nexus。
stops-nexus.bat:停止 Nexus。
uninstall-nexus.bat:与 install-nexus.bat 相对应,负责卸载 Nexus 服务。
双击运行 install-nexus.bat 安装 Nexus 服务,然后运行 start-nexus.bat 启动服务。
注意:如果你是直接点击 install-nexus.bat的话会提示如下异常:需要以管理员cmd窗口进行运行。
OpenSCManager failed - 拒绝访问。 (0x5)
启动后访问:http://localhost:8081/nexus
注:访问地址和3.x还是有点差距的,3.x只需要ip+端口
点击首页右上角的“Log In”按钮,在登录页面输入用户名和密码(默认分别为:admin 和 admin123 ),最后点击“Log In”按钮登录。
登录之后的界面:
很显然2.x跟3.x页面大不相同,连菜单都不一样了,这也就是Nexus两个大的版本在同步更新的原因,准确的来说3.x对于2.x来说就是重构
3.4.3 修改仓库
仓库类型 | 说明 |
---|---|
proxy | 某个远程仓库的代理 |
group | 存放:通过 Nexus 获取的第三方 jar 包 |
hosted | 存放:本团队其他开发人员部署到 Nexus 的jar 包 |
仓库版本的讲解
仓库 | 描述 |
---|---|
maven-central | 中央仓库,默认从https://repo1.maven.org/maven2/拉取软件包,可配置 |
maven-public | 公共仓库,存储发行版和快照版的软件包,即发行版和快照版的软件包都会在public中 |
maven-releases | 发行版仓库,软件包稳定后,发布到该仓库,团队内使用 |
maven-snapshots | 快照版本仓库,用于测试软件,发布到线上 |
替换一下镜像源。点击maven-central.
替换一下。点到下面,然偶点击save
3.4.4 通过Nexus下载jar包
修改本地maven的核心配置文件settings.xml,设置新的本地仓库地址
<localRepository>D:\java\mvn</localRepository>
修改镜像源。
把上面的镜像地址,复制粘贴到路径中
<mirror><id>nexus-mine</id><mirrorOf>central</mirrorOf><name>Nexus mine</name><url>http://localhost:8081/repository/maven-public/</url></mirror>
把上图中看到的地址复制出来即可。如果我们在前面允许了匿名访问,到这里就够了。但如果我们禁用了匿名访问,那么接下来我们还要继续配置 settings.xml,记得修改密码:
<server><id>nexus-mine</id><username>admin</username><password>atguigu</password></server>
这里需要格外注意:server 标签内的 id 标签值必须和 mirror 标签中的 id 值一样。
创建一个maven项目。设置maven配置
设置完成,点击编译按钮。这样子 远程仓库就会下载
让我们到远程仓库上,就会看见依赖
3.4.5 把jar包部署到Nexus中
在maven仓库中配置
<distributionManagement><snapshotRepository><id>nexus-mine</id><name>Nexus Snapshot</name><url>http://localhost:8081/repository/maven-snapshots/</url></snapshotRepository></distributionManagement>
添加配置
上网查看是否上传成功
如果报错
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:3.1.1:deploy (default-deploy) on project maven-test: Failed to deploy artifacts: Could not transfer artifact com.lkcoffee.framework:maven-test:pom:1.0-20240726.071734-1 from/to nexus-mine (http://localhost:8081/repository/maven-snapshots/): status code: 401, reason phrase: Unauthorized (401) -> [Help 1]
很明显了,deploy的时候,权限不够大。于是排查maven setting配置文件,最终在……配置节点中增加如下配置,问题解决:
记得添加一下东西。
这是server的id(注意不是用户登陆的id),该id与distributionManagement中repository元素的id相匹配。
3.4.6 引用别人部署的 jar 包
在项目中配置
<repositories><repository><id>nexus-mine</id><name>nexus-mine</name><url>http://localhost:8081/repository/maven-snapshots/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>true</enabled></releases></repository></repositories>
或者在maven的setting,xml中配置
<profile><id>nexus</id><repositories><repository><id>nexus-mine</id><name>nexus-mine</name><url>http://localhost:8081/repository/maven-snapshots/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>true</enabled></releases></repository></repositories>
</profile>
参考资料
三、基于 IDEA 创建 Maven 工程_idea 新maven项目-CSDN博客
四、基于 IDEA 进行 Maven 工程构建_idea创建一个maven工程-CSDN博客