从入门到精通:Java项目依赖问题终极解决指南(2026典藏版·含Maven生命周期全解析)
从入门到精通:Java项目依赖问题终极解决指南(2026典藏版·含Maven生命周期全解析)
本文收录于「Java开发实战进阶」专栏 作者:技术小伙伴
前言
在Java项目开发中,依赖管理是每个开发者都无法回避的话题。你是否曾经遇到过这样的场景:
- 项目编译正常,运行时却抛出
NoSuchMethodError或ClassNotFoundException - Maven构建时提示
package com.sun.jersey.api.client.config does not exist - 引入一个新依赖后,原有的功能突然报错
- 同一个依赖出现了多个版本,不知道最终哪个生效
这些问题,本质上都是依赖管理出了问题。本文将带你系统性地掌握Java项目依赖问题的诊断与解决之道,从Maven生命周期底层原理,到各类工具的逐行详细使用,再到企业级最佳实践,一篇文章彻底搞定。
全文共分为七大篇章:生命周期原理篇、核心概念篇、IDE工具篇、命令行工具篇、仓库配置篇、规范强制篇、Gradle工具链篇、企业级实践篇、实战案例篇。每个知识点都会拆解到最细粒度,确保你读完就能上手。
一、Maven生命周期原理篇:构建的底层逻辑
在深入依赖管理之前,必须先理解Maven的生命周期机制。因为所有构建命令(如mvn clean package)都是围绕生命周期设计的,理解它能让你真正掌控构建过程。
1.1 什么是Maven生命周期?
Maven的生命周期是对所有构建过程进行抽象和统一的一套规范。它定义了项目构建的各个步骤及其执行顺序,但生命周期本身不做事——实际的工作由绑定在生命周期阶段上的插件完成。
这种设计的好处是:
- 标准化:所有Maven项目遵循相同的构建规范
- 可扩展:通过配置插件可以自定义构建行为
- 自动化:执行一个命令会自动触发前面所有阶段
1.2 三套相互独立的生命周期
Maven包含三套生命周期,它们彼此独立,可以单独调用:
| 生命周期 | 作用 | 包含的主要阶段 |
|---|---|---|
| clean | 清理项目 | pre-clean, clean, post-clean |
| default | 项目构建(核心) | validate, compile, test, package, install, deploy 等23个阶段 |
| site | 生成项目站点 | pre-site, site, post-site, site-deploy |
重要:每个生命周期内部的阶段是有顺序的,执行后面的阶段会自动执行前面的所有阶段。但三套生命周期之间互不影响——执行mvn clean package会先执行clean周期的clean(及其前序),再执行default周期的package(及其前序),但不会执行site周期。
1.3 clean生命周期详解
clean生命周期的目的是清理项目,移除上一次构建生成的文件。包含三个阶段:
| 阶段 | 说明 |
|---|---|
| pre-clean | 执行清理前需要完成的工作 |
| clean | 移除所有上一次构建生成的文件(默认删除target目录) |
| post-clean | 执行清理后需要完成的工作 |
命令示例:
# 只执行clean阶段(会自动执行pre-clean)
mvn clean
# 执行post-clean(会自动执行pre-clean和clean)
mvn post-clean
1.4 default生命周期详解(最核心)
default生命周期定义了真正构建项目所需的所有步骤,共有23个阶段。我们日常使用的compile、test、package、install、deploy都是它的阶段。
常用阶段列表(按执行顺序):
| 阶段 | 说明 | 对应插件目标(默认) |
|---|---|---|
| validate | 验证项目正确性和必要信息是否可用 | |
| initialize | 初始化构建状态 | |
| generate-sources | 生成源代码 | |
| process-sources | 处理源代码 | |
| generate-resources | 生成资源文件 | |
| process-resources | 处理并复制主资源文件到输出目录 | resources:resources |
| compile | 编译主源代码 | compiler:compile |
| process-classes | 处理编译生成的文件 | |
| generate-test-sources | 生成测试源代码 | |
| process-test-sources | 处理测试源代码 | |
| generate-test-resources | 生成测试资源文件 | |
| process-test-resources | 处理并复制测试资源文件 | resources:testResources |
| test-compile | 编译测试代码 | compiler:testCompile |
| process-test-classes | 处理测试编译生成的文件 | |
| test | 运行单元测试 | surefire:test |
| prepare-package | 打包前的准备工作 | |
| package | 打包成可分发的格式(如jar、war) | jar:jar 或 war:war |
| pre-integration-test | 集成测试前准备 | |
| integration-test | 执行集成测试 | |
| post-integration-test | 集成测试后清理 | |
| verify | 验证包的有效性 | |
| install | 安装到本地仓库,供本地其他项目使用 | install:install |
| deploy | 部署到远程仓库,供其他开发人员使用 | deploy:deploy |
核心规律:执行后面的阶段,会自动执行前面所有阶段。例如:
# 执行package,会自动执行validate→compile→test→package
mvn package
# 执行install,会自动执行到install的所有阶段
mvn install
# 执行deploy,会自动执行全部阶段
mvn deploy
1.5 site生命周期详解
site生命周期的目的是生成和发布项目站点:
| 阶段 | 说明 |
|---|---|
| pre-site | 执行生成站点前的工作 |
| site | 生成项目站点文档 |
| post-site | 执行生成站点后的工作 |
| site-deploy | 将生成的站点发布到服务器 |
1.6 生命周期与插件绑定机制
生命周期阶段本身不做任何实际工作,实际任务由绑定到阶段上的插件目标完成。
内置绑定:Maven为不同的打包类型(jar、war、pom)预设了默认的插件绑定。例如:
process-resources阶段绑定resources:resourcescompile阶段绑定compiler:compiletest阶段绑定surefire:test
自定义绑定:可以在POM中配置将插件目标绑定到指定阶段:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<!-- 将jar-no-fork目标绑定到compile阶段 -->
<phase>compile</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
查看插件信息:使用mvn help:describe查看插件的默认绑定阶段:
mvn help:describe -Dplugin=org.apache.maven.plugins:maven-compiler-plugin
1.7 命令行调用规则总结
| 命令 | 实际执行的阶段 |
|---|---|
mvn clean | clean周期的pre-clean, clean |
mvn test | default周期的validate→...→test |
mvn package | default周期的validate→...→package |
mvn clean install | clean周期的pre-clean, clean + default周期的全部阶段到install |
mvn clean deploy site-deploy | clean周期 + default周期全部 + site周期全部 |
重要结论:
- 阶段有顺序,执行后面前面的自动执行
- 生命周期独立,可以跨周期调用
- 插件绑定,实际工作由插件完成
二、核心概念篇:依赖管理的底层逻辑
理解了生命周期后,我们再来深入依赖管理本身。
2.1 什么是依赖管理?
Maven通过POM文件实现声明式依赖管理,开发者只需在XML中定义所需库的名称和版本,Maven会自动从仓库下载依赖及其传递性依赖。
每个依赖的三要素:
- groupId:组织标识,如
com.google.guava - artifactId:项目标识,如
guava - version:版本号,如
31.1-jre
2.2 传递性依赖:冲突的根源
当你引入一个库时,它会自动引入它所依赖的其他库。例如:
- 项目依赖A,A依赖B(v1.0)
- 项目也依赖C,C依赖B(v2.0)
这时问题就来了:项目最终应该使用B的哪个版本? 这就是典型的依赖冲突。
2.3 Maven默认的冲突解决规则
Maven采用两条原则解决依赖冲突:
① 最短路径优先:依赖路径越短,优先级越高
- 路径A→B→Guava:30.1(深度2)
- 路径C→Guava:31.0(深度1)
- 最终使用深度更短的31.0版本
② 第一声明优先:如果路径深度相同,先声明的依赖生效
- 路径A→B→Guava:30.1(深度2)
- 路径A→C→Guava:31.0(深度2)
- 按POM中依赖声明的顺序,谁先出现就用谁
2.4 依赖范围(Scope)详解
依赖范围决定了依赖在哪些阶段生效,正确设置可以避免很多问题:
| Scope | 说明 | 编译有效 | 测试有效 | 运行有效 | 典型示例 |
|---|---|---|---|---|---|
| compile | 默认值,所有阶段都可用 | ✅ | ✅ | ✅ | 核心业务依赖 |
| provided | 由JDK或容器提供 | ✅ | ✅ | ❌ | Servlet API |
| runtime | 运行时需要,编译时不需要 | ❌ | ✅ | ✅ | JDBC驱动 |
| test | 仅在测试时使用 | ❌ | ✅ | ❌ | JUnit |
| system | 本地系统路径提供 | ✅ | ✅ | ❌ | 特殊本地Jar |
| import | 从BOM导入依赖管理 | - | - | - | 用于dependencyManagement |
重点:
- 如果把
compile范围的依赖误设为test,编译期就会报找不到类的错误 provided范围的依赖在打包时不会被包含,因为容器(如Tomcat)已提供
传递依赖的范围传递规则:
- 如果直接依赖是
compile,传递依赖如果是compile或runtime,则对当前项目生效 - 如果直接依赖是
provided,传递依赖不会生效 - 如果直接依赖是
test,传递依赖不会生效
2.5 依赖调解与依赖管理
除了默认规则,Maven还提供了几种控制依赖的方式:
| 机制 | 说明 |
|---|---|
| 依赖调节 | 上述的最短路径优先和第一声明优先规则 |
| 依赖管理 | 在<dependencyManagement>中显式指定版本,强制使用 |
| 依赖排除 | 通过<exclusions>排除某个传递依赖 |
| 依赖可选 | 通过<optional>true</optional>标记,避免强制传递 |
三、仓库体系篇:依赖的来源与配置
3.1 三种仓库类型
Maven仓库分为三类,构成依赖解析的完整链路:
| 仓库类型 | 位置/地址 | 说明 |
|---|---|---|
| 本地仓库 | ~/.m2/repository | 优先从本地查找,不存在则从远程下载 |
| 中央仓库 | https://repo.maven.apache.org/maven2 | 官方公共仓库,包含海量开源组件 |
| 远程仓库 | 公司私服(如Nexus)或镜像 | 企业级项目必备,可缓存公共依赖、存放私有构件 |
3.2 配置远程仓库
在pom.xml中配置远程仓库:
<repositories>
<repository>
<id>aliyun-maven</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy> <!-- never/always/daily/interval:X -->
</releases>
<snapshots>
<enabled>false</enabled> <!-- 生产环境建议禁用快照 -->
</snapshots>
</repository>
</repositories>
3.3 配置镜像加速
国内访问中央仓库速度较慢,推荐配置阿里云镜像。在~/.m2/settings.xml中配置:
<mirrors>
<mirror>
<id>aliyun-maven</id>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf> <!-- 拦截所有对中央仓库的请求 -->
</mirror>
</mirrors>
mirrorOf高级语法:
*:匹配所有仓库external:*:匹配所有非本地仓库repo1,repo2:匹配指定ID的仓库*,!internal-repo:匹配所有,但排除internal-repo
3.4 私有仓库认证配置
如果公司有私有仓库需要认证,在settings.xml中配置:
<servers>
<server>
<id>private-repo</id> <!-- 必须与repository的id一致 -->
<username>deploy-user</username>
<password>加密后的密码</password>
</server>
</servers>
推荐使用Maven密码加密功能:mvn --encrypt-password。
3.5 多仓库配置策略
企业级项目建议采用分层策略:
- 基础依赖:使用阿里云等公共镜像
- 私有构件:配置企业Nexus仓库
- 特殊需求:在项目POM中补充
四、IDE工具篇:Maven Helper插件完全使用指南
4.1 安装步骤
- 打开IDEA,进入
File -> Settings(Mac:Preferences) - 选择
Plugins,搜索Maven Helper - 点击
Install,重启IDEA
4.2 打开Dependency Analyzer
打开项目的pom.xml,底部会出现 "Dependency Analyzer" 选项卡。点击后可看到三个视图:
- Conflict:自动检测并列出所有存在冲突的依赖
- All Dependencies as List:列表形式展示所有依赖
- All Dependencies as Tree:树形结构展示完整依赖层级
4.3 查看依赖树
在树形视图中,可以清晰看到每个依赖的来源路径:
demo-project
├─ org.springframework:spring-core:5.3.10 (compile)
│ └─ commons-logging:commons-logging:1.2 (compile)
└─ org.slf4j:slf4j-api:1.7.32 (compile)
4.4 冲突检测与一键排除
操作步骤:
- 切换到"Conflicts"标签,冲突项用红色字体高亮
- 右键点击红色冲突项
- 选择 "Exclude" 命令
- 插件自动在
pom.xml中生成<exclusion>配置
排除后效果:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
4.5 搜索与过滤
- 顶部搜索框:输入关键词快速过滤
- 右侧下拉菜单:按scope过滤(compile、test等)
五、命令行工具篇:Maven原生命令全解析
5.1 mvn dependency:tree - 查看依赖树
基本用法:
mvn dependency:tree
高级过滤:
# 按范围过滤
mvn dependency:tree -Dincludes=*:*:*:compile
# 按包名过滤
mvn dependency:tree -Dincludes=com.fasterxml.jackson:*
# 排除特定依赖
mvn dependency:tree -Dexcludes=org.slf4j
5.2 mvn dependency:analyze - 分析依赖使用情况
发现两类问题:
- 未使用的依赖:声明了但代码中没有用到
- 使用了但未声明的依赖:代码中直接使用了,但依赖是通过传递性引入的
mvn dependency:analyze
输出示例:
[WARNING] Used undeclared dependencies found:
org.springframework:spring-context:jar:5.3.10:compile
[WARNING] Unused declared dependencies found:
junit:junit:jar:4.13.2:test
5.3 mvn dependency:analyze-duplicate - 检测重复依赖
生成详细冲突报告:
mvn dependency:analyze-duplicate
输出示例:
[INFO] Duplicate dependencies found:
[INFO] com.google.guava:guava:jar:30.1-jre (version managed from 31.0.1-jre)
[INFO] +- com.example:service:jar:1.0:compile
[INFO] \- com.example:client:jar:1.2:compile (depends on 31.0.1-jre)
5.4 mvn dependency:resolve - 检查依赖解析结果
当怀疑依赖没有正确下载或解析时使用:
mvn dependency:resolve
5.5 mvn dependency:purge-local-repository - 清理本地仓库
当本地仓库依赖损坏时使用:
# 清理并重新下载所有依赖
mvn dependency:purge-local-repository
# 只清理特定依赖
mvn dependency:purge-local-repository -DmanualIncludes=com.google.guava:guava
5.6 mvn versions:display-dependency-updates - 检查依赖更新
定期检查依赖是否有新版本:
mvn versions:display-dependency-updates
六、规范强制篇:Maven Enforcer Plugin完整配置
6.1 完整配置示例
在pom.xml中添加:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.6.2</version>
<executions>
<execution>
<id>enforce-rules</id>
<phase>validate</phase> <!-- 在编译前执行 -->
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<fail>true</fail>
<rules>
<!-- 规则1:强制所有依赖版本收敛 -->
<dependencyConvergence/>
<!-- 规则2:禁止某些有漏洞的版本 -->
<bannedDependencies>
<excludes>
<exclude>log4j:log4j:1.2.*</exclude>
<exclude>org.apache.logging.log4j:log4j-core:[2.0,2.15)</exclude>
</excludes>
<message>禁止使用存在漏洞的日志版本</message>
</bannedDependencies>
<!-- 规则3:强制使用版本不低于传递依赖要求的版本 -->
<requireUpperBoundDeps/>
<!-- 规则4:禁止重复的依赖声明 -->
<banDuplicatePomDependencyVersions/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
6.2 常用规则详解
| 规则 | 作用 |
|---|---|
| dependencyConvergence | 强制所有依赖版本收敛,不允许冲突 |
| bannedDependencies | 禁止某些特定依赖 |
| requireUpperBoundDeps | 确保使用的版本不低于传递依赖要求的版本 |
| requireReleaseDeps | 强制使用release版本,禁止SNAPSHOT |
| requireMavenVersion | 强制Maven版本 |
| requireJavaVersion | 强制Java版本 |
6.3 命令行参数
# 手动执行检查
mvn enforcer:enforce
# 跳过所有检查
mvn clean install -Denforcer.skip=true
# 只检查特定规则
mvn enforcer:enforce -Denforcer.rules=dependencyConvergence
七、解决方案篇:依赖冲突的七种解决策略
7.1 策略一:依赖排除(Exclusion)
最常用的解决方式,排除不需要的传递依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
</exclusion>
</exclusions>
</dependency>
7.2 策略二:版本锁定(Dependency Management)
在父POM中统一管理版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
子模块声明时无需指定版本。
7.3 策略三:强制指定版本
利用"最短路径优先"原则,直接在项目中声明需要的版本。
7.4 策略四:可选依赖(Optional)
开发基础组件时,避免强制传递依赖:
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>2.5.1</version>
<optional>true</optional>
</dependency>
这样使用者不会被迫引入pinyin4j。
7.5 策略五:使用BOM(Bill of Materials)
对于Spring Boot等大型框架,使用官方BOM确保版本兼容:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
7.6 策略六:属性锁定
在properties中定义版本,实现一处修改处处生效:
<properties>
<guava.version>31.1-jre</guava.version>
<jackson.version>2.15.2</jackson.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
7.7 策略七:Enforcer插件自动检测
使用dependencyConvergence规则,在构建时自动检测并终止构建。
八、企业级实践篇:完整解决方案
8.1 私有仓库搭建(Nexus)
快速搭建步骤:
# 下载Nexus
wget https://download.sonatype.com/nexus/3/latest-unix.tar.gz
tar -zxvf latest-unix.tar.gz
cd nexus-3.x.x-xx/bin
./nexus start
访问http://localhost:8081,默认账号admin/admin123。
8.2 OWASP Dependency Check - 安全漏洞扫描
在pom.xml中配置:
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>8.4.0</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<format>ALL</format>
<failBuildOnCVSS>7</failBuildOnCVSS> <!-- CVSS≥7时构建失败 -->
</configuration>
</plugin>
8.3 CI/CD完整集成方案
Jenkins Pipeline示例:
pipeline { agent any stages { stage('Dependency Analysis') { parallel { stage('Tree') { steps { sh 'mvn dependency:tree > dependencies.txt' archiveArtifacts 'dependencies.txt' } } stage('Enforcer') { steps { sh 'mvn enforcer:enforce' } } stage('Security') { steps { sh 'mvn dependency-check:check' } } stage('Updates') { steps { sh 'mvn versions:display-dependency-updates > updates.txt' } } } } } }
8.4 依赖管理最佳实践总结
| 阶段 | 最佳实践 |
|---|---|
| 开发期 | 安装Maven Helper,随时查看依赖树 |
| 提交前 | 执行mvn enforcer:enforce检查规范 |
| CI阶段 | 集成dependency check和版本收敛检查 |
| 发版前 | 使用versions插件检查依赖更新 |
| 日常维护 | 通过私有仓库管理内部依赖版本 |
九、实战案例篇:完整问题解决全流程
案例一:Guava版本冲突导致NoSuchMethodError
问题现象:启动时报错java.lang.NoSuchMethodError: com.google.common.cache.CacheBuilder.maximumSize
诊断步骤:
- 查看异常栈,确认是Guava的方法找不到
- 使用Maven Helper打开"Conflicts"标签,看到Guava红色警告
- 追踪来源:
com.example:demo:1.0-SNAPSHOT +- com.example:service:1.0:compile | \- com.google.guava:guava:30.1-jre:compile \- com.example:client:1.2:compile \- com.google.guava:guava:31.0.1-jre:compile
解决方案:在父POM中统一版本:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
</dependencyManagement>
案例二:SLF4J多个绑定警告
问题现象:启动时出现SLF4J的"Multiple bindings"警告
诊断步骤:
mvn dependency:tree | grep -E "(slf4j|logback|log4j)"
输出显示同时有logback-classic和slf4j-log4j12。
解决方案:使用Maven Helper排除多余的日志实现,或显式排除:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
案例三:依赖未传递问题
问题现象:声明了A依赖,但编译时报A的某个传递依赖不存在
诊断步骤:
mvn dependency:tree查看A的依赖树- 发现A的传递依赖没有出现
- 检查A的pom,发现该依赖被标记为
<optional>true</optional>
解决方案:在项目中显式声明缺失的依赖。
案例四:循环依赖检测
检测命令:
mvn dependency:analyze -Dverbose -DignoreNonCompile
解决方案:
- 重构代码结构,提取公共模块
- 使用接口隔离
- 使用
<optional>true</optional>标记可选依赖
十、Gradle工具链篇(补充)
对于使用Gradle的项目,核心概念相通但命令不同:
10.1 查看依赖树
gradle dependencies
10.2 自定义冲突解决策略
configurations.all { resolutionStrategy { force 'org.slf4j:slf4j-api:1.7.36' failOnVersionConflict() } }
10.3 解决能力冲突
configurations.configureEach { resolutionStrategy.capabilitiesResolution.withCapability("javax.mail:mail") { select("com.sun.mail:jakarta.mail:1.6.5") } }
十一、总结
掌握本文的知识点,你将能够:
- 理解底层:明白Maven生命周期三套体系的运作原理
- 快速定位:使用Maven Helper和命令行工具,几分钟内找到冲突根源
- 精准解决:掌握七种解决策略,对症下药
- 提前预防:借助Enforcer Plugin和CI集成,将问题扼杀在萌芽
- 企业级实践:搭建私有仓库,建立依赖管理规范
某制造企业的实践显示,实施完整的依赖管理体系后,依赖相关故障响应时间从平均4小时缩短至45分钟,构建效率提升40%以上。
希望这份详尽的指南能帮助你彻底摆脱"依赖地狱"的困扰。如果你在实践中遇到本文未覆盖的场景,欢迎在评论区留言交流。
参考资料:[1] 阿里云开发者社区·Maven生命周期与插件 [2] Worktile·Maven项目与其他项目区别 [3] 腾讯云·Maven实战进阶:依赖冲突解决 [4] 百度开发者中心·Maven多仓库与镜像配置 [5] 阿里云开发者社区·Maven生命周期和依赖传递 [6] Maven官方文档·依赖管理 [7] 亿速云·Maven依赖冲突自动化解决 [8] 百度开发者中心·Maven依赖管理全攻略 [9] 51Testing·Maven实战(四)生命周期
知识点测试
读完文章了?来测试一下你对知识点的掌握程度吧!
评论区
使用 GitHub 账号登录后即可发表评论,支持 Markdown 格式。
如果评论系统无法加载,请确保:
- 您的网络可以访问 GitHub
- giscus GitHub App 已安装到仓库
- 仓库已启用 Discussions 功能