Maven 依赖范围与排除

ops/2025/2/9 3:29:54/

Maven 是一个强大的构建工具,依赖管理是其核心功能之一。在大型项目中,可能会有多个模块和库之间的依赖关系,Maven 通过 依赖范围(Scope)依赖排除(Exclusions) 机制来控制依赖的使用方式,并解决版本冲突的问题。

本篇文章将深入探讨:

  1. Maven 依赖范围(Scope)
  2. 如何排除冲突的依赖(Exclusions)
  3. 实战案例:处理依赖冲突

1. Maven 依赖范围(Scope)

1.1 什么是依赖范围?

依赖范围(Scope)决定了依赖项在 Maven 构建生命周期中的可用性,即它在编译、测试、运行等不同阶段是否生效。

Maven 提供了以下 6 种依赖范围

范围(Scope)作用可用阶段
compile(默认)适用于所有阶段(编译、测试、运行)compiletestruntimepackageinstalldeploy
provided由 JDK 或容器提供,不会打包到 JAR/WARcompiletest
runtime编译时不需要,运行时需要runtimepackageinstalldeploy
test仅在测试阶段可用,不会被打包test
system本地提供,不从 Maven 仓库下载compiletest
import用于导入 BOM(Bill of Materials)仅用于 dependencyManagement

1.2 依赖范围详解

1. compile(默认)
  • 作用:默认范围,适用于所有构建阶段(编译、测试、运行)。
  • 适用场景:项目需要该依赖进行编译和运行。

示例

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version><scope>compile</scope>
</dependency>

行为

  • 编译时可用 ✅
  • 测试时可用 ✅
  • 运行时可用 ✅
  • 参与打包 ✅

2. provided
  • 作用:类似 compile,但不会打包到最终的 JAR/WAR,因为它由 JDK 或容器(如 Tomcat)提供。
  • 适用场景:如 Servlet API、JDBC API,在 Web 服务器或应用容器中已存在。

示例

<dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope>
</dependency>

行为

  • 编译时可用 ✅
  • 测试时可用 ✅
  • 运行时不可用 ❌
  • 参与打包 ❌

3. runtime
  • 作用:运行时需要,编译时不需要。
  • 适用场景:如 JDBC 驱动,编译时不直接引用,但运行时需要加载。

示例

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.26</version><scope>runtime</scope>
</dependency>

行为

  • 编译时不可用 ❌
  • 测试时可用 ✅
  • 运行时可用 ✅
  • 参与打包 ✅

4. test
  • 作用:仅在测试阶段可用,不会打包到最终的应用中。
  • 适用场景:如 JUnit、Mockito 等测试框架。

示例

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>

行为

  • 编译时不可用 ❌
  • 测试时可用 ✅
  • 运行时不可用 ❌
  • 参与打包 ❌

5. system
  • 作用:依赖必须提供本地路径,Maven 不会从远程仓库下载。
  • 适用场景:使用本地的 JAR(但推荐使用 provided 代替)。

示例

<dependency><groupId>com.example</groupId><artifactId>custom-lib</artifactId><version>1.0</version><scope>system</scope><systemPath>${project.basedir}/lib/custom-lib.jar</systemPath>
</dependency>

行为

  • 编译时可用 ✅
  • 测试时可用 ✅
  • 运行时可用 ✅
  • 参与打包 ✅

6. import
  • 作用:用于 dependencyManagement,引入 BOM(Bill of Materials)。
  • 适用场景:Spring Boot 采用 BOM 机制,管理一组依赖的版本。

示例

<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.5.0</version><scope>import</scope><type>pom</type></dependency></dependencies>
</dependencyManagement>

2. 依赖排除(Exclusions)

2.1 依赖传递性

如果 A 依赖 B,而 B 依赖 C,则 A 会自动引入 C,这被称为传递性依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.9</version>
</dependency>

spring-web 依赖 commons-logging,如果项目中已使用 SLF4J,可能会发生冲突


2.2 排除依赖

为了避免冲突,可以使用 <exclusions> 排除不需要的传递性依赖。

示例

<dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.3.9</version><exclusions><exclusion><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId></exclusion></exclusions>
</dependency>

3. 实战案例:解决依赖冲突

3.1 查看依赖树

当出现依赖冲突时,可以使用 mvn dependency:tree 查看依赖关系。

mvn dependency:tree

示例输出

[INFO] com.example:my-app:jar:1.0-SNAPSHOT
[INFO] ├─ org.springframework:spring-core:jar:5.3.9:compile
[INFO] │  ├─ commons-logging:commons-logging:jar:1.2:compile
[INFO] ├─ org.slf4j:slf4j-api:jar:1.7.30:compile

如果 commons-loggingslf4j 冲突,可以使用 <exclusions> 解决。


4. 总结

  • Maven 提供 6 种依赖范围

    • compile(默认):适用于所有阶段
    • provided:编译需要,运行时由容器提供
    • runtime:运行时需要,编译时不需要
    • test:仅测试阶段可用
    • system:本地提供,需手动指定路径
    • import:用于 BOM
  • 可以使用 <exclusions> 解决依赖冲突

  • 使用 mvn dependency:tree 检查依赖冲突

掌握 Maven 依赖管理的这些技巧,可以有效提高项目的稳定性和可维护性!🚀


http://www.ppmy.cn/ops/156873.html

相关文章

Leecode刷题C语言之全排列②

执行结果:通过 执行用时和内存消耗如下&#xff1a; int* path; int pathTop; int** ans; int ansTop; int cnt[8];//标记path中是否已有此索引值&#xff0c;这也是同46题不同点 void backTracking(int* nums,int numsSize,int startIndex,int** returnColumnSizes){if(pathT…

自动化软件测试的基本流程

一、自动化测试的准备 1.1 了解测试系统 首先对于需要测试的系统我们需要按照软件需求说明书明确软件功能。这里以智慧养老系统作为案例进行测试&#xff0c;先让我们看看该系统的登录界面和用户管理界面。 登录界面&#xff1a; 登录成功默认界面&#xff1a; 用户管理界面…

Jenkins基础篇 - Jenkins介绍与安装示例

文章目录 1. Jenkins介绍2. Jenkins安装2.1 使用War文件安装2.1.1 硬件要求2.1.2 软件要求2.1.3 安装Java2.1.4 安装Jenkins 3 安装后设置向导3.1 解锁Jenkins3.2 自定义Jenkins插件3.3 创建第一个管理员用户3.4 实例配置3.5 Jenkins已就绪&#xff01;&#xff01;&#xff01…

VC播放mp3的方法

1、使用msi库 #include <mmsystem.h> #pragma comment(lib,"winmm.lib") .......//打开文件MCI_OPEN_PARMS mciOpen; mciOpen.lpstrDeviceType _T("mpegvideo"); mciOpen.lpstrElementName _T("c://1.mp3"); MCIERROR mciError mci…

【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目

解决idea至少创建jdk17项目 问题 idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗?解决 问题 idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗 我本来以为是 IDEA 版本更新导致的 Bug&#xff0c;开始还没在意。 直到我今天自己初始化项目时才发现&am…

102,【2】buuctf web [第二章 web进阶]XSS闯关

进入靶场 点击看看 前情提要 如果只想得到flag时 不想做题时&#xff0c;把level由1不断往下修改就可通过一关又一关 最后在url处修改level为7即可得到flag 通过做题破解每一关的话&#xff0c;就如下 操作 第一关 修改url <script>alert(xss)</script> 第二…

《具身智能时代:机器人具身抓取技术的前沿探索与应用综述》

自2022年GPT等大模型的爆发以来&#xff0c;人工智能领域以语言模型为代表的预训练模型在多个领域掀起了创新浪潮。到了2024年&#xff0c;DeepSeek等新技术进一步加速了具身智能的发展&#xff0c;特别是在机器人领域&#xff0c;预训练模型的引入深刻改变了传统的感知、决策和…

一次报警了解:direct path read、enq: KO - fast object checkpoint

背景 今天突然接到订单超时报警&#xff0c;数据库的状态确实惊出一身冷汗&#xff0c;查看系统日志正常&#xff0c;数据库日志正常&#xff0c;load 1-3之间&#xff0c;Session 连接200左右&#xff0c;未发现有负载。于是生成一个ASH报告&#xff0c;感觉比平时要慢很多&am…