Maven 基础
Maven 坐标、生命周期与依赖管理:如何用约定构建、测试与打包 Java 项目。
[!info] related notes
Maven 基础
这个概念为什么出现
多模块、第三方依赖、测试与打包不能靠手工 javac。Maven 以 POM 坐标 + 约定目录 + 生命周期 成为 Java 构建事实标准之一。
[!abstract] 一句话理解 Maven 用
groupId:artifactId:version管理构件,用标准生命周期(validate→compile→test→package→…)与插件执行构建;pom.xml是项目模型。
最小可运行示例
场景:构建普通 Java JAR
以下完整 POM 以 Maven 3.9.9、JDK 21 验证。将源码放在 src/main/java 后执行命令;普通 JAR 不会自动包含依赖或 Main-Class,也不自动变成可执行应用。
<!-- pom.xml -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>shop</groupId>
<artifactId>order-service</artifactId>
<version>0.1.0</version>
<properties>
<maven.compiler.release>21</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
</plugins>
</build>
</project>
常用命令:
mvn package
mvn test
mvn dependency:tree
目录约定:
src/main/java
src/main/resources
src/test/java
结合场景再看三个关注点
- 约定优于配置减少脚本。
- 依赖传递要用
dependency:tree审计。 - compiler release 约束语言级别、字节码目标及对应 Java 平台 API;不能替代依赖兼容性与目标运行时测试。
核心概念与准确模型
1. 坐标与仓库
- 本地仓库默认
~/.m2/repository,可通过 settings 配置。 - 中央/私服
2. 依赖范围
compile 用于主代码编译及运行;provided 编译时可见、运行由环境提供;runtime 不参与主代码编译;test 仅用于测试。普通 JAR 默认不打包依赖,不能把 scope 理解成“是否嵌入 JAR”的开关。
3. 生命周期与插件
指定阶段会执行同一生命周期中它及之前的阶段。install 不隐含 clean,后者属于独立生命周期。Java JAR 项目通常由 Surefire 在 test 阶段运行单元测试;集成测试需显式配置 Failsafe 等插件,不能假设 package 自动覆盖。
4. BOM 与 dependencyManagement
dependencyManagement 管理依赖的版本等默认信息,不会自动引入依赖;模块仍需在 dependencies 中声明使用。导入 BOM 时使用 type=pom、scope=import,BOM 也不管理构建插件版本。
边界情况与反直觉行为
- 传递依赖版本冲突取“近者优先”等规则——要会看 tree。
- 插件版本不锁可能导致 CI 漂移。
- 与 Gradle 互操作发布仍靠 Maven 坐标生态。
常见误区
[!warning] 常见误区:盲加依赖不看许可证与传递树 供应链与体积风险。
工程实践
- 锁插件版本。
- 用 wrapper(
mvnw)。 - 失败构建保留 surefire 报告。
- 多模块按边界拆 reactor。
本节总结
- POM+生命周期+约定目录
- 坐标生态是 Java 依赖中心
- 会读 dependency tree
自测题
mvn package默认跑测试吗?- test scope 依赖为何不进主产物?
参考答案
- 默认到达 test 阶段;能否实际发现并执行测试取决于测试插件、框架和命名配置。
-DskipTests通常跳过执行但仍编译测试;-Dmaven.test.skip=true还跳过测试编译。 - test scope 仅测试编译/运行可见且不传递给消费者;普通 JAR 本来就不会自动嵌入依赖。
延伸阅读与资料来源
| 资料 | 类型 | 支撑内容 |
|---|---|---|
| Maven Users Centre | 官方 | 指南 |
| POM Reference | 官方 | 模型 |