Maven之依赖管理

Maven之依赖管理

    • 一、Maven依赖管理的核心价值
    • 二、依赖的基本配置(坐标与范围)
      • 2.1 依赖坐标(GAV)
      • 2.2 依赖范围(scope)
        • 示例:常用依赖范围配置
    • 三、依赖传递与冲突解决
      • 3.1 依赖传递性
        • 示例:依赖传递
      • 3.2 依赖冲突及解决
        • 3.2.1 冲突的表现
        • 3.2.2 Maven默认的冲突调解规则
        • 示例:路径最近原则
        • 示例:声明优先原则
        • 3.2.3 手动解决冲突(排除与锁定)
          • 方式1:排除依赖(exclusions)
          • 方式2:锁定版本(dependencyManagement)
    • 三、依赖管理的高级配置
      • 3.1 可选依赖(optional)
      • 3.2 导入依赖(import)
      • 3.3 快照依赖(SNAPSHOT)
    • 四、实战:依赖管理最佳实践
      • 4.1 单模块项目依赖管理
      • 4.2 多模块项目依赖管理
        • 1. 父模块pom.xml(parent.pom)
        • 2. 子模块pom.xml(module-web/pom.xml)
    • 四、常见问题与避坑指南
      • 4.1 依赖下载失败(Could not find artifact)
      • 4.2 国内镜像配置(解决下载慢问题)
      • 4.3 依赖范围使用不当
    • 总结:依赖管理的核心要点

Java项目开发中手动管理jar包是一件繁琐且容易出错的工作(如版本冲突、缺失依赖),Maven的依赖管理功能通过标准化的配置,自动下载、存储和管理jar包,极大提升了开发效率。

一、Maven依赖管理的核心价值

在没有Maven的时代,开发者需要手动下载jar包、放入项目lib目录,并处理jar包之间的依赖关系(如使用Spring需要同时导入commons-logging)。这种方式的问题:

  • 版本混乱:同一jar包可能有多个版本,手动选择易出错;
  • 依赖缺失:复杂框架(如Spring Boot)依赖数十个jar包,手动收集困难;
  • 冗余存储:每个项目都保存一份jar包,浪费磁盘空间;
  • 升级困难:升级框架版本需手动替换所有相关jar包。

Maven的依赖管理通过以下方式解决这些问题:

  1. 中央仓库:统一存储jar包,自动下载并缓存到本地仓库;
  2. 依赖坐标:通过groupId+artifactId+version唯一标识jar包;
  3. 依赖传递:自动引入间接依赖(如导入Spring-core会自动引入commons-logging);
  4. 冲突解决:提供默认的依赖调解规则,避免版本冲突。

二、依赖的基本配置(坐标与范围)

2.1 依赖坐标(GAV)

Maven通过GAV坐标唯一标识一个依赖(jar包),在pom.xml中配置:

<dependencies><!-- 依赖配置 --><dependency><groupId>org.springframework</groupId> <!-- 组织ID(公司/组织唯一标识) --><artifactId>spring-core</artifactId>   <!-- 项目ID(模块唯一标识) --><version>5.3.20</version>             <!-- 版本号 --></dependency>
</dependencies>

坐标三要素

  • groupId:组织或公司标识(如org.springframework代表Spring官方);
  • artifactId:项目或模块标识(如spring-core是Spring的核心模块);
  • version:版本号(如5.3.20,RELEASE表示稳定版,SNAPSHOT表示快照版)。

作用:Maven根据GAV从中央仓库下载jar包,并存储到本地仓库(默认~/.m2/repository)。

2.2 依赖范围(scope)

依赖范围控制依赖在编译、测试、运行三个阶段的可见性,常用范围:

范围(scope)编译时有效测试时有效运行时有效打包时包含典型场景
compile(默认)核心依赖(如Spring-core)
test测试依赖(如JUnit)
provided容器提供的依赖(如Servlet-api)
runtime运行时依赖(如MySQL驱动)
system本地jar包(非仓库获取,不推荐)
示例:常用依赖范围配置
<dependencies><!-- 1. compile(默认):编译、测试、运行都需要 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version><!-- 省略scope,默认compile --></dependency><!-- 2. test:仅测试阶段需要(如JUnit) --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!-- 3. provided:运行时由容器提供(如Tomcat提供Servlet-api) --><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><!-- 4. runtime:编译时不需要,运行时需要(如MySQL驱动) --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>8.0.33</version><scope>runtime</scope></dependency>
</dependencies>

关键说明

  • provided依赖不会被打包(如Servlet-api,避免与Tomcat自带的冲突);
  • test依赖仅在src/test/java中可用,主代码无法引用。

三、依赖传递与冲突解决

3.1 依赖传递性

Maven的依赖具有传递性:若A依赖B,B依赖C,则A会自动依赖C(无需手动配置)。

示例:依赖传递
A项目依赖spring-context(5.3.20)
└── spring-context依赖spring-core(5.3.20)└── spring-core依赖commons-logging(1.2)

此时A项目的pom.xml只需配置spring-context,Maven会自动引入spring-core和commons-logging:

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version>
</dependency>

优势:简化配置,无需手动引入间接依赖。

3.2 依赖冲突及解决

依赖传递可能导致同一jar包出现多个版本(如A依赖C-1.0,B依赖C-2.0),引发冲突。

3.2.1 冲突的表现
  • NoSuchMethodError:调用的方法在当前版本中不存在(如使用低版本jar包但调用高版本方法);
  • ClassNotFoundException:类不存在(版本不兼容导致);
  • 日志混乱:同一框架的不同版本日志输出异常。
3.2.2 Maven默认的冲突调解规则

Maven提供默认规则解决冲突,优先级:

  1. 路径最近原则:直接依赖优先于间接依赖(如A直接依赖C-2.0,同时通过B依赖C-1.0,则使用C-2.0);
  2. 声明优先原则:路径相同时,在pom.xml中声明靠前的依赖优先。
示例:路径最近原则
A依赖B(B依赖C-1.0)
A直接依赖C-2.0
→ 最终使用C-2.0(直接依赖路径更近)
示例:声明优先原则
A依赖B(B依赖C-1.0)
A依赖D(D依赖C-2.0)
→ 若B在pom.xml中声明比D靠前,使用C-1.0;反之使用C-2.0
3.2.3 手动解决冲突(排除与锁定)

默认规则可能不符合需求,需手动干预:

方式1:排除依赖(exclusions)

通过exclusions排除不需要的间接依赖:

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.20</version><!-- 排除间接依赖的commons-logging --><exclusions><exclusion><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions>
</dependency><!-- 手动引入更高版本的日志依赖 -->
<dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.36</version>
</dependency>

适用场景:排除冲突的间接依赖,替换为其他依赖(如用SLF4J替代commons-logging)。

方式2:锁定版本(dependencyManagement)

通过dependencyManagement统一管理版本,强制所有依赖使用指定版本:

<!-- 父pom或当前pom中配置 -->
<dependencyManagement><dependencies><!-- 锁定Spring-core版本为5.3.20 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.3.20</version></dependency></dependencies>
</dependencyManagement><!-- 实际依赖(无需指定version,自动使用锁定版本) -->
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><!-- 版本由dependencyManagement控制 --></dependency>
</dependencies>

优势

  • 集中管理版本,避免分散配置导致的不一致;
  • 子模块可继承父模块的版本锁定(适合多模块项目)。

三、依赖管理的高级配置

3.1 可选依赖(optional)

若A依赖B,且B中的某些功能并非所有使用者都需要,可将B标记为optional(可选依赖),避免B被传递:

<!-- A项目的pom.xml -->
<dependency><groupId>com.example</groupId><artifactId>module-b</artifactId><version>1.0.0</version><optional>true</optional> <!-- 可选依赖,不传递 -->
</dependency>

效果:其他项目依赖A时,不会自动依赖B;若需要B,需手动配置。

3.2 导入依赖(import)

import用于导入其他pom.xml中的dependencyManagement配置(类似“引用”),适合多模块项目统一版本:

<!-- 定义一个统一的版本管理pom(如dependency-management.pom) -->
<project><groupId>com.example</groupId><artifactId>dependency-management</artifactId><version>1.0.0</version><packaging>pom</packaging><dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.3.20</version></dependency></dependencies></dependencyManagement>
</project><!-- 在其他项目中导入 -->
<dependencyManagement><dependencies><dependency><groupId>com.example</groupId><artifactId>dependency-management</artifactId><version>1.0.0</version><type>pom</type><scope>import</scope> <!-- 导入依赖管理配置 --></dependency></dependencies>
</dependencyManagement>

优势:避免在每个项目中重复配置dependencyManagement,实现版本集中管控。

3.3 快照依赖(SNAPSHOT)

快照版本(version-SNAPSHOT结尾)用于开发中的临时版本,Maven会定期更新(默认每天检查一次):

<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.4.0-SNAPSHOT</version> <!-- 快照版本 -->
</dependency>

特点

  • 适合团队内部开发(频繁迭代,未正式发布);
  • 正式环境应使用RELEASE版本(稳定,不更新)。

四、实战:依赖管理最佳实践

4.1 单模块项目依赖管理

<project><modelVersion>4.0.0</modelVersion><groupId>com.example</groupId><artifactId>single-module</artifactId><version>1.0.0</version><!-- 集中管理版本 --><properties><spring.version>5.3.20</spring.version><junit.version>4.13.2</junit.version></properties><dependencyManagement><dependencies><!-- Spring相关依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version> <!-- 引用properties中的版本 --></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency><!-- 测试依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement><!-- 实际依赖(无需指定version) --><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency></dependencies>
</project>

关键

  • 通过properties定义版本变量,便于统一修改;
  • dependencyManagement集中管控,实际依赖简化配置。

4.2 多模块项目依赖管理

多模块项目(如父模块+子模块)通过父模块统一管理依赖:

1. 父模块pom.xml(parent.pom)
<project><groupId>com.example</groupId><artifactId>parent</artifactId><version>1.0.0</version><packaging>pom</packaging> <!-- 父模块必须为pom --><!-- 子模块 --><modules><module>module-web</module><module>module-service</module></modules><!-- 统一版本管理 --><properties><spring.version>5.3.20</spring.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency></dependencies></dependencyManagement>
</project>
2. 子模块pom.xml(module-web/pom.xml)
<project><parent><groupId>com.example</groupId><artifactId>parent</artifactId><version>1.0.0</version></parent><artifactId>module-web</artifactId><dependencies><!-- 继承父模块的版本,无需指定version --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency></dependencies>
</project>

优势

  • 所有子模块共享父模块的版本配置,确保一致性;
  • 升级版本只需修改父模块,无需逐个修改子模块。

四、常见问题与避坑指南

4.1 依赖下载失败(Could not find artifact)

错误Could not find artifact org.springframework:spring-core:jar:5.3.20 in central

原因

  • 网络问题(无法连接中央仓库);
  • GAV坐标错误(如拼写错误、版本不存在);
  • 本地仓库缓存损坏(下载到一半的文件)。

解决方案

  • 检查网络连接,或配置国内镜像(如阿里云仓库);
  • 确认GAV坐标正确(可在Maven中央仓库搜索验证);
  • 删除本地仓库中对应目录(如~/.m2/repository/org/springframework/spring-core/5.3.20),重新下载。

4.2 国内镜像配置(解决下载慢问题)

中央仓库在国外,下载慢可配置阿里云镜像:

<!-- 在settings.xml中配置(~/.m2/settings.xml) -->
<settings><mirrors><mirror><id>aliyunmaven</id><name>阿里云公共仓库</name><url>https://maven.aliyun.com/repository/public</url><mirrorOf>central</mirrorOf> <!-- 替代中央仓库 --></mirror></mirrors>
</settings>

4.3 依赖范围使用不当

问题provided依赖在运行时缺失(如Servlet-api在Tomcat外运行报错)。

原因provided依赖在运行时不包含,若应用脱离容器运行(如单元测试),会找不到类。

解决方案

  • 测试时可添加test范围的依赖:
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>
<!-- 测试时使用 -->
<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>test</scope>
</dependency>

总结:依赖管理的核心要点

  1. 基础配置:通过GAV坐标定义依赖,scope控制依赖范围;
  2. 冲突解决:优先使用dependencyManagement锁定版本,必要时通过exclusions排除冲突;
  3. 最佳实践
    • 集中管理版本(properties+dependencyManagement);
    • 多模块项目通过父模块统一版本;
    • 合理使用providedtest范围,减少打包体积;
    • 配置国内镜像,提升下载速度。

掌握依赖管理不仅能避免版本冲突,还能提升项目的可维护性,在实际项目中观察依赖树(通过mvn dependency:tree命令),了解依赖传递关系,遇到冲突时能快速定位并解决。

若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/90629.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/90629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Unity实战100例】Unity资源下载系统开发流程详解(移动端、PC端 ,局域网控制台服务)

目录 一、项目概述 二、服务器开发 1、配置文件设计 1、加载配置 2. 处理客户端请求 3. 文件下载处理 三、客户端开发 1、配置管理 1、配置加载与保存 2、下载任务管理 1、任务类设计 2、下载队列管理 3、核心下载流程 四、UI系统实现 五、部署与测试 1、服务…

[Python] -进阶理解7- Python中的内存管理机制简析

Python(尤其是 CPython)采用自动内存管理机制,核心包括引用计数(Reference Counting)与垃圾回收机制(Garbage Collection),并配合专门的内存池和分配器机制来提升效率与减少碎片。 这套机制隐藏在开发者视线之外,Python 开发者无需手动申请或释放内存。 二、Python 内…

云祺容灾备份系统AWS S3对象存储备份与恢复实操手册

1、创建密钥访问AWS控制台&#xff0c;鼠标移至右上角账户处&#xff0c;在弹出菜单中点击安全凭证&#xff0c;如图1。图1在弹出页面中&#xff0c;下滑找到访问密钥&#xff0c;并点击创建访问密钥&#xff0c;如图2。图2选择其他&#xff0c;并点击下一步&#xff0c;如图3。…

使用 LLaMA 3 8B 微调一个 Reward Model:从入门到实践

本文将介绍如何基于 Meta 的 LLaMA 3 8B 模型构建并微调一个 Reward Model&#xff0c;它是构建 RLHF&#xff08;基于人类反馈的强化学习&#xff09;系统中的关键一环。我们将使用 Hugging Face 的 transformers、trl 和 peft 等库&#xff0c;通过参数高效微调&#xff08;L…

matrix-breakout-2-morpheus靶场攻略

靶场使用将压缩包解压到一个文件夹中&#xff0c;用虚拟机应用新建虚拟机&#xff0c;扫描虚拟机&#xff0c;扫描那个文件夹&#xff0c;就可以把虚拟机扫出来了&#xff0c;然后启动虚拟机这时候靶场启动后&#xff0c;咱们现在要找到这个靶场。靶场是网页形式的&#xff0c;…

MySQL 复制表

MySQL 复制表 概述 在数据库管理中&#xff0c;复制表是一项常用的操作。它允许数据库管理员将一个表中的数据复制到另一个表中&#xff0c;无论是同一个数据库还是不同的数据库。MySQL数据库提供了多种方法来复制表&#xff0c;本文将详细介绍MySQL复制表的过程、方法及其应用…

『哈哥赠书 - 55期』-『码农职场:IT人求职就业手册』

文章目录⭐️ 码农职场&#xff1a;IT人求职就业手册⭐️ 本书简介⭐️ 作者简介⭐️ 编辑推荐这是一本专为广大IT行业求职者量身定制的指南&#xff0c;提供了从职前准备到成功就业的全方位指导&#xff0c;涵盖了职业目标规划、自我技能评估、求职策略、简历准备以及职场心理…

单片机学习课程

单片机学习课程 课程介绍 单片机技术作为现代工业自动化、电子电气、通信及物联网等领域的主流技术&#xff0c;早已深度融入我们生活与生产的各个角落。从常见家电到自动化公共设施&#xff0c;都离不开单片机的支持。同时&#xff0c;它也是学习 ARM 嵌入式系统、FPGA 设计等…

【AcWing 143题解】最大异或对

AcWing 143. 最大异或对 【题目描述】 在查看解析之前&#xff0c;先给自己一点时间思考哦&#xff01; 【题解】 本题要求给定一个整数序列&#xff0c;找出其中任意两个数进行异或运算后&#xff0c;结果的最大值是多少。由于数据规模较大&#xff0c;我们不能简单地通过两…

SQLAlchemy 2.0简单使用

记录一下SQLAlchemy 2.0连接mysql数据库的方法及简单使用 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎&#xff0c;链接到mysql engine create_engine(mysqlpymysql://{username}:{password}{ip}:3306/{database_name}…

如何创建或查看具有 repo 权限的 GitHub 个人访问令牌(PAT)

要创建或查看具有 repo 权限的 GitHub 个人访问令牌(PAT),请按照以下步骤操作: 一、生成具有 repo 权限的 PAT 登录 GitHub 访问 GitHub 官网,使用你的账户登录。 进入开发者设置 点击右上角头像,选择 Settings(设置) → 左侧菜单中选择 Developer settings(开发者设…

【AI时代速通QT】第五节:Qt Creator如何引入第三方库,以OpenCV为例

目录 引言 一、第一步&#xff1a;万事开头难 - 准备工作 1.1 获取并“安装”OpenCV 1.2 创建一个新的Qt项目 1.3 建立专业的项目目录结构 二、第二步&#xff1a;核心操作 - 配置.pro文件 2.1 方式一&#xff1a;图形化向导&#xff08;适合初次体验&#xff09; 2.2 …

使用Clion开发STM32(Dap调试)

使用Clion开发STM32环境配置ST-Link无法下载OpenOCDST-Link调试Dap-Link调试Debug配置查看寄存器值之前写了一篇文章关于如何用VSCode配合EIDE插件开发STM32 最近研究了如何使用Clion开发STM32 环境配置 使用Clion开发STM32需要用到4个工具&#xff1a;Clion、STM32CubeMX、…

人工智能-python-OpenCV 中 `release()` 和 `destroy()` 的区别

文章目录OpenCV 中 release() 和 destroy() 的区别1. release()常见使用场景&#xff1a;代码示例&#xff1a;作用&#xff1a;2. destroy()常见使用场景&#xff1a;代码示例&#xff1a;作用&#xff1a;3. 总结&#xff1a;4. 何时使用小结&#xff1a;OpenCV 中 release()…

[RPA] 日期时间练习案例

案例1根据日期拆分表格根据表格中不同日期&#xff0c;创建多个对应日期名称的Sheet页(名称格式为"yyyy-mm-dd")&#xff0c;并将同一日期的订单拷贝至对应Sheet页日期时间练习题1.xlsx流程搭建&#xff1a;实现效果&#xff1a;

2025.7.27文献阅读-基于深度神经网络的半变异函数在高程数据普通克里金插值中的应用

2025.7.27周报一、文献阅读题目信息摘要创新点实验一、半变异函数拟合二、普通克里金插值三、结果对比分析四、实验结果结论不足以及展望一、文献阅读 题目信息 题目&#xff1a; Application of a semivariogram based on a deep neural network to Ordinary Kriging interp…

用unity开发教学辅助软件---幼儿绘本英语拼读

记录完整项目的制作&#xff0c;借鉴了大佬被代码折磨的狗子 “unity创建《找不同》游戏 图片编辑器”一文。 &#xff08;建议通过目录阅读本文哦~&#xff09; 项目演示&#xff1a; 幼儿英语教辅幼儿英语绘本教学游戏整体架构 游戏开发中设计的整体框架 游戏的总体功能框架…

《Java 程序设计》第 5 章 - 数组详解

引言在 Java 编程中&#xff0c;数组是一种基础且重要的数据结构&#xff0c;它允许我们将多个相同类型的元素存储在一个连续的内存空间中&#xff0c;通过索引快速访问。掌握数组的使用是学习 Java 集合框架、算法等高级知识的基础。本章将从数组的创建、使用开始&#xff0c;…

基于Spring Boot的可盈保险合同管理系统的设计与实现(源码+论文)

一、相关技术 技术/工具描述SSM框架在JavaWeb开发中&#xff0c;SSM框架&#xff08;Spring Spring MVC MyBatis&#xff09;是流行的选择。它既没有SSH框架的臃肿&#xff0c;也没有SpringMVC的简化&#xff0c;属于中间级别&#xff0c;更灵活且易于编写和理解。MyBatis框…

​​XSLT:XML转换的“魔法棒”​

大家好&#xff01;今天我们来聊聊 ​​XSLT​​&#xff08;Extensible Stylesheet Language Transformations&#xff09;&#xff0c;一种用于转换和呈现XML文档的神奇工具。如果你曾需要将一堆枯燥的XML数据变成精美的HTML网页、PDF报告&#xff0c;或其他XML格式&#xff…