名称: maven-dependency-management 用户可调用: false 描述: 当管理 Maven 依赖、解决依赖冲突、配置 BOMs 或优化依赖树在 Java 项目中时使用。 允许工具: [Read, Write, Edit, Bash, Glob, Grep]
Maven 依赖管理
掌握 Maven 依赖管理,包括依赖声明、作用域管理、版本解析、BOMs 和依赖树优化。
概述
Maven 的依赖管理是 Java 项目构建系统的基石。它处理传递性依赖、版本冲突,并提供控制多模块项目中依赖解析的机制。
依赖声明
基本依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
带作用域的依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
可选依赖
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<optional>true</optional>
</dependency>
依赖作用域
可用作用域
| 作用域 | 编译类路径 | 测试类路径 | 运行时类路径 | 传递性 |
|---|---|---|---|---|
| compile | 是 | 是 | 是 | 是 |
| provided | 是 | 是 | 否 | 否 |
| runtime | 否 | 是 | 是 | 是 |
| test | 否 | 是 | 否 | 否 |
| system | 是 | 是 | 否 | 否 |
| import | 不适用 | 不适用 | 不适用 | 不适用 |
作用域示例
<!-- Compile 作用域(默认)- 到处可用 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<!-- Provided - 编译时可用,不打包 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- Runtime - 仅在运行时需要 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.1</version>
<scope>runtime</scope>
</dependency>
<!-- Test - 仅用于测试 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.8.0</version>
<scope>test</scope>
</dependency>
版本管理
基于属性的版本
<properties>
<spring-boot.version>3.2.0</spring-boot.version>
<junit.version>5.10.1</junit.version>
<jackson.version>2.16.0</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
版本范围
<!-- 精确版本 -->
<version>1.0.0</version>
<!-- 大于或等于 -->
<version>[1.0.0,)</version>
<!-- 小于 -->
<version>(,1.0.0)</version>
<!-- 范围包含 -->
<version>[1.0.0,2.0.0]</version>
<!-- 范围排除 -->
<version>(1.0.0,2.0.0)</version>
最新版本(不推荐)
<!-- 生产环境避免使用 -->
<version>LATEST</version>
<version>RELEASE</version>
依赖管理部分
集中版本
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>2.16.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 当在 dependencyManagement 中声明时,无需版本 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
BOM(材料清单)导入
<dependencyManagement>
<dependencies>
<!-- Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- AWS SDK BOM -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.23.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- JUnit BOM -->
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>5.10.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
排除
排除传递性依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加替代 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
排除日志框架
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
依赖分析
查看依赖树
# 完整依赖树
mvn dependency:tree
# 按构件过滤
mvn dependency:tree -Dincludes=org.slf4j
# 输出到文件
mvn dependency:tree -DoutputFile=deps.txt
# 详细输出显示冲突解决
mvn dependency:tree -Dverbose
分析依赖
# 查找未使用的声明依赖和使用的未声明依赖
mvn dependency:analyze
# 仅显示问题
mvn dependency:analyze-only
# 包括测试作用域
mvn dependency:analyze -DignoreNonCompile=false
列出依赖
# 列出所有依赖
mvn dependency:list
# 按作用域列出
mvn dependency:list -DincludeScope=runtime
冲突解决
Maven 默认策略
Maven 使用“最近定义优先”解决版本冲突:
A -> B -> C 1.0
A -> C 2.0
结果:使用 C 2.0(距离根最近)
强制版本
<dependencyManagement>
<dependencies>
<!-- 在所有模块中强制特定版本 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>
</dependencies>
</dependencyManagement>
使用 Enforcer 插件进行版本控制
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<id>enforce</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<dependencyConvergence/>
<requireUpperBoundDeps/>
<banDuplicatePomDependencyVersions/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
多模块项目
父 POM 依赖管理
<!-- parent/pom.xml -->
<project>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
<!-- module/pom.xml -->
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>module</artifactId>
<dependencies>
<!-- 版本从父级继承 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
</dependency>
</dependencies>
</project>
仓库配置
中央仓库
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
私有仓库
<repositories>
<repository>
<id>company-repo</id>
<url>https://nexus.company.com/repository/maven-public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
在 Settings.xml 中配置仓库
<!-- ~/.m2/settings.xml -->
<settings>
<servers>
<server>
<id>company-repo</id>
<username>${env.REPO_USER}</username>
<password>${env.REPO_PASS}</password>
</server>
</servers>
</settings>
最佳实践
- 使用 dependencyManagement - 在父 POM 中集中版本
- 导入 BOMs - 使用维护良好的 BOMs 处理框架依赖
- 避免版本范围 - 固定精确版本以保证可复现性
- 定期更新 - 保持依赖更新以确保安全
- 最小化作用域 - 使用适当的作用域减小包大小
- 排除未使用的 - 移除未使用的传递性依赖
- 记录排除原因 - 注释为什么需要排除
- 运行 dependency:analyze - 定期检查问题
- 使用 Enforcer 插件 - 确保依赖收敛
- 锁定版本 - 使用 versions-maven-plugin 进行更新
常见陷阱
- 版本冲突 - 传递性依赖版本不匹配
- 缺失排除 - 不同构件中的重复类
- 错误作用域 - compile、runtime、provided 混淆
- 过时依赖 - 旧版本中的安全漏洞
- 循环依赖 - 模块 A 依赖 B 依赖 A
- 快照用于生产 - 在发布版本中使用 SNAPSHOT 版本
- 系统作用域 - 硬编码路径破坏可移植性
- 可选误用 - 将必需依赖标记为可选
故障排除
调试依赖解析
# 启用调试输出
mvn dependency:tree -X
# 显示冲突解决
mvn dependency:tree -Dverbose=true
强制重新下载
# 清除本地仓库缓存
mvn dependency:purge-local-repository
# 强制更新
mvn -U clean install
检查有效 POM
# 查看解析后的依赖版本
mvn help:effective-pom
何时使用此技能
- 向项目添加新依赖
- 解决版本冲突
- 设置多模块项目依赖
- 配置 BOM 导入
- 优化依赖树
- 故障排除类路径问题
- 升级依赖版本
- 排除有问题的传递性依赖