依赖声明必须写在标签内,每个至少含、、;scope控制生效阶段,默认compile;传递依赖冲突用精准排除;本地jar应安装到本地仓库而非用system scope。

依赖声明必须写在 <dependencies></dependencies> 标签下
不是所有 XML 节点都能放依赖,pom.xml 中只有 <dependencies></dependencies> 及其子节点 <dependency></dependency> 是合法位置。写在 <build></build>、<properties></properties> 或根节点下都无效,Maven 会直接忽略。
每个 <dependency></dependency> 至少要包含三个字段:<groupid></groupid>、<artifactid></artifactid>、<version></version>。例如引入 Jackson JSON 处理库:
<dependency><groupid>com.fasterxml.jackson.core</groupid><artifactid>jackson-databind</artifactid><version>2.15.2</version></dependency>
-
<groupid></groupid>通常对应 Java 包名倒序(如org.springframework),但不是绝对;它本质是 Maven 仓库中的命名空间 -
<artifactid></artifactid>是模块名,和 Jar 文件名前缀一致(如jackson-databind-2.15.2.jar) -
<version></version>推荐用具体版本号,避免用LATEST或RELEASE—— 它们已被 Maven 3.9+ 默认禁用,且破坏构建可重现性
scope 属性决定依赖何时生效,别乱设 provided 或 test
scope 控制依赖参与编译、运行、测试等阶段的时机。默认是 compile,即全生命周期可用;但常见误用是把本该运行时才需要的包(如 Servlet API)设为 compile,导致打包进 WAR 后与容器冲突。
-
provided:仅编译和测试期有效,运行时不提供(如javax.servlet-api)。打成 WAR 部署到 Tomcat 时,必须设这个,否则会和容器自带的类重复 -
test:只在mvn test阶段可用(如junit-jupiter)。若在 main 代码里 import,编译直接报错 -
runtime:不参与编译,但运行时需要(如 JDBC 驱动mysql-connector-java)。IDE 可能提示“找不到符号”,这是正常现象
依赖传递性常引发版本冲突,优先用 <exclusions></exclusions> 而非盲目升级
Maven 自动拉取间接依赖(比如你引入 Spring Boot Starter Web,它又依赖 Spring Core、Jackson、Tomcat Embed 等),但不同 starter 可能带不同版本的同一依赖(如两个库分别依赖 slf4j-api:1.7.36 和 slf4j-api:2.0.7),此时 Maven 按“路径最短优先”选一个,可能选错。
查冲突用命令:mvn dependency:tree -Dverbose。看到警告如 omitted for conflict with 1.7.36 就说明被丢弃了。
- 不要一上来就全局
<properties></properties>覆盖所有版本,容易引发兼容问题 - 精准排除干扰项更安全:在冲突依赖的
<dependency></dependency>内加<exclusions></exclusions>,例如排除掉某个 starter 带的旧版 Logback - 真正需要统一版本时,用
<dependencymanagement></dependencymanagement>块集中声明,它只“约定”不“引入”,子模块仍需显式声明依赖
本地 Jar 包不能直接扔进 lib/ 目录,得用 system scope 或安装到本地仓库
把第三方 Jar 拷进项目 lib/ 并在 IDE 里手动 Add to Build Path,Maven 打包(mvn package)时根本不会包含它 —— 因为 Maven 不认这个路径。
- 临时方案(不推荐长期用):用
systemscope,指定<systempath></systempath>绝对或相对路径,但该依赖不会上传到远程仓库,协作时别人构建必失败 - 正确做法:用
mvn install:install-file把 Jar 安装进本地~/.m2/repository,再像普通依赖一样声明<groupid></groupid>、<artifactid></artifactid>、<version></version> - 企业级场景应搭建私有 Nexus/Artifactory,把内部 Jar deploy 上去,而非依赖本地文件
依赖管理真正的复杂点不在写法,而在于理解“谁真正加载了这个类”——运行时 ClassLoader 层级、容器环境、打包方式(jar vs war vs fat jar)都会让同一个 pom.xml 表现出不同行为。动手前先想清楚:这个包,是在编译期检查语法?测试期构造对象?还是运行期连接数据库?答案不同,配置就完全不同。










