最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
62-Maven核心细解
时间:2026-06-03 12:10:02 编辑:袖梨 来源:一聚教程网
Maven作为Java生态中主流的项目管理和构建工具,其核心价值在于简化构建流程并增强依赖管理、项目标准化及插件扩展能力。以下内容将深入剖析Maven的依赖机制、生命周期、插件开发与多模块构建等关键知识点。
Maven核心详解
一、知识概述

本文会详细解析Maven的核心原理,涵盖依赖管理、生命周期、插件开发以及多模块项目构建等内容,并配有实际代码示例。
Maven的核心价值
- 标准化项目结构:统一的目录布局。
- 依赖管理:自动下载和管理第三方库。
- 构建生命周期:标准化的构建流程。
- 插件扩展:丰富的插件生态。
- 多模块支持:大型项目模块化管理。
二、知识点详细讲解
2.1 Maven项目结构
标准目录布局
my-project/
├── pom.xml # 项目对象模型文件
├── src/
│ ├── main/
│ │ ├── java/ # 主代码目录
│ │ │ └── com/example/app/
│ │ │ ├── App.java
│ │ │ └── service/
│ │ ├── resources/ # 主资源目录
│ │ │ ├── application.properties
│ │ │ └── logback.xml
│ │ ├── webapp/ # Web应用目录(WAR项目)
│ │ │ ├── WEB-INF/
│ │ │ │ └── web.xml
│ │ │ └── index.jsp
│ │ └── filters/ # 资源过滤文件
│ │ └── filter.properties
│ └── test/
│ ├── java/ # 测试代码目录
│ │ └── com/example/app/
│ │ └── AppTest.java
│ ├── resources/ # 测试资源目录
│ │ └── test-application.properties
│ └── filters/ # 测试过滤文件
├── target/ # 构建输出目录
│ ├── classes/ # 编译后的class文件
│ ├── test-classes/ # 测试class文件
│ └── my-project-1.0.jar # 构建产物
└── README.md
POM文件详解
4.0.0
com.example
my-project
1.0.0
jar
My Project
A sample Maven project
2024
Apache License, Version 2.0
repo
john
John Doe
[email protected]
Example Inc.
architect
developer
UTF-8
UTF-8
17
17
6.1.0
5.10.0
1.18.30
org.springframework.boot
spring-boot-dependencies
3.2.0
pom
import
org.springframework
spring-context
${spring.version}
org.projectlombok
lombok
${lombok.version}
provided
org.junit.jupiter
junit-jupiter
${junit.version}
test
clean install
${project.artifactId}-${project.version}
src/main/resources
true
**/*.properties
**/*.xml
**/*.yml
org.apache.maven.plugins
maven-compiler-plugin
3.11.0
${maven.compiler.source}
${maven.compiler.target}
${project.build.sourceEncoding}
-parameters
org.apache.maven.plugins
maven-surefire-plugin
3.1.2
false
methods
4
org.apache.maven.plugins
maven-jar-plugin
3.3.0
com.example.app.App
true
lib/
org.springframework.boot
spring-boot-maven-plugin
3.2.0
dev
true
dev
prod
prod
org.apache.maven.plugins
maven-jar-plugin
**/application-dev.*
aliyun
Aliyun Maven Repository
true
false
aliyun-plugin
Aliyun Maven Plugin Repository
releases
Internal Releases
snapshots
Internal Snapshots
2.2 依赖管理机制
依赖范围(Scope)
/**
* Maven依赖范围详解
*
* scope取值说明:
*
* 1. compile(默认)
* - 编译、测试、运行都有效
* - 打包时包含
*
* 2. provided
* - 编译、测试有效,运行无效
* - 打包时不包含(由容器提供)
* - 典型应用:servlet-api、lombok
*
* 3. runtime
* - 测试、运行有效,编译无效
* - 打包时包含
* - 典型应用:JDBC驱动
*
* 4. test
* - 仅测试有效
* - 打包时不包含
* - 典型应用:JUnit、Mockito
*
* 5. system
* - 与provided类似,但需要指定本地路径
* - 不推荐使用
*
* 6. import
* - 仅用于dependencyManagement
* - 导入BOM(Bill of Materials)
*/
依赖范围与classpath关系
┌─────────────┬──────────────┬──────────────┬──────────────┐
│ Scope │ Compile │ Test │ Runtime │
├─────────────┼──────────────┼──────────────┼──────────────┤
│ compile │ │ │ │
│ provided │ │ │ │
│ runtime │ │ │ │
│ test │ │ │ │
│ system │ │ │ │
└─────────────┴──────────────┴──────────────┴──────────────┘
依赖传递性
/**
* 依赖传递性规则:
*
* 假设 A -> B -> C(A依赖B,B依赖C)
*
* C能否传递到A,取决于:
* 1. B对C的scope
* 2. A对B的scope
*
* 传递性矩阵:
*
* B的scope
* compile provided runtime test
* A的scope
* compile
* provided
* runtime
* test
*
* 示例:
* 项目A -> 项目B(compile)-> 项目C(compile)
* 结果:A可以使用C
*
* 项目A -> 项目B(compile)-> 项目C(provided)
* 结果:A不能使用C
*/
依赖冲突解决
com.example
A
1.0
com.example
B
1.0
com.example
A
1.0
com.example
C
com.example
C
2.0
com.example
C
2.0
依赖分析命令
# 查看依赖树
mvn dependency:tree# 查看依赖树(指定范围)
mvn dependency:tree -Dscope=compile# 分析依赖
mvn dependency:analyze# 查看有效POM
mvn help:effective-pom# 查看依赖列表
mvn dependency:list# 解析依赖
mvn dependency:resolve# 查看插件依赖
mvn dependency:resolve-plugins
2.3 构建生命周期
三套生命周期
/**
* Maven有三套相互独立的生命周期:
*
* 1. Clean Lifecycle(清理)
* pre-clean -> 执行清理前的工作
* clean -> 清理上一次构建生成的文件
* post-clean -> 执行清理后的工作
*
* 2. Default Lifecycle(构建)
* validate -> 验证项目是否正确
* initialize -> 初始化构建状态
* generate-sources -> 生成源代码
* process-sources -> 处理源代码
* generate-resources -> 生成资源文件
* process-resources -> 处理资源文件
* compile -> 编译源代码
* process-classes -> 处理编译后的文件
* generate-test-sources -> 生成测试源代码
* process-test-sources -> 处理测试源代码
* generate-test-resources -> 生成测试资源
* process-test-resources -> 处理测试资源
* test-compile -> 编译测试代码
* process-test-classes -> 处理测试编译后的文件
* test -> 运行测试
* prepare-package -> 准备打包
* package -> 打包
* pre-integration-test -> 集成测试前准备
* integration-test -> 集成测试
* post-integration-test -> 集成测试后处理
* verify -> 验证
* install -> 安装到本地仓库
* deploy -> 部署到远程仓库
*
* 3. Site Lifecycle(站点文档)
* pre-site -> 生成站点前的工作
* site -> 生成项目站点文档
* post-site -> 生成站点后的工作
* site-deploy -> 发布站点到服务器
*/
生命周期执行顺序
# 执行clean生命周期
mvn clean# 执行default生命周期到compile阶段
mvn compile# 执行default生命周期到package阶段
mvn package# 执行clean和default两个生命周期
mvn clean package# 执行多个阶段
mvn clean test package# 跳过测试
mvn package -DskipTests# 跳过测试编译和测试执行
mvn package -Dmaven.test.skip=true# 指定环境
mvn package -P prod# 离线模式(使用本地缓存)
mvn package -o# 调试模式
mvn package -X
2.4 插件机制
常用插件配置
org.apache.maven.plugins
maven-compiler-plugin
3.11.0
17
17
17
UTF-8
-parameters
-Xlint:unchecked
org.projectlombok
lombok
1.18.30
org.mapstruct
mapstruct-processor
1.5.5.Final
org.apache.maven.plugins
maven-surefire-plugin
3.1.2
false
methods
4
**/*Test.java
**/*IntegrationTest.java
-Xmx512m
-Djava.security.egd=file:/dev/./urandom
test
org.apache.maven.plugins
maven-jar-plugin
3.3.0
com.example.app.App
true
lib/
${maven.build.timestamp}
${user.name}
${project.version}
**/application-dev.*
org.apache.maven.plugins
maven-source-plugin
3.3.0
attach-sources
package
jar-no-fork
org.apache.maven.plugins
maven-javadoc-plugin
3.6.2
UTF-8
UTF-8
UTF-8
none
private
true
attach-javadocs
package
jar
org.apache.maven.plugins
maven-resources-plugin
3.3.1
UTF-8
true
@
${*}
org.apache.maven.plugins
maven-dependency-plugin
3.6.1
copy-dependencies
package
copy-dependencies
${project.build.directory}/lib
runtime
org.springframework.boot
spring-boot-maven-plugin
3.2.0
com.example.app.Application
org.projectlombok
lombok
repackage
org.codehaus.mojo
versions-maven-plugin
2.16.2
false
net.revelc.code.formatter
formatter-maven-plugin
2.23.0
${project.basedir}/formatter.xml
LF
format
org.apache.maven.plugins
maven-checkstyle-plugin
3.3.1
checkstyle.xml
UTF-8
true
true
validate
validate
check
2.5 多模块项目
父POM配置
4.0.0
com.example
parent-project
1.0.0
pom
common
api
service
web
17
3.2.0
3.5.5
org.springframework.boot
spring-boot-dependencies
${spring.boot.version}
pom
import
com.example
common
${project.version}
com.example
api
${project.version}
org.projectlombok
lombok
provided
org.springframework.boot
spring-boot-maven-plugin
${spring.boot.version}
子模块POM
4.0.0
com.example
parent-project
1.0.0
common
jar
org.apache.commons
commons-lang3
cn.hutool
hutool-all
5.8.24
4.0.0
com.example
parent-project
1.0.0
service
jar
com.example
common
org.springframework.boot
spring-boot-starter
com.baomidou
mybatis-plus-boot-starter
${mybatis.plus.version}
4.0.0
com.example
parent-project
1.0.0
web
jar
com.example
service
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
repackage
模块依赖关系
web(启动模块)
└── service(业务逻辑)
└── common(公共模块)
└── api(接口定义)
三、可运行Java代码示例
Maven插件开发示例
package com.example.maven.plugin;import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;/**
* 自定义Maven插件:代码统计
* 使用:mvn code-stat:stat
*/
@Mojo(name = "stat", defaultPhase = LifecyclePhase.COMPILE)
public class CodeStatMojo extends AbstractMojo {
/**
* 源代码目录
*/
@Parameter(defaultValue = "${project.build.sourceDirectory}", readonly = true)
private File sourceDirectory;
/**
* 项目对象
*/
@Parameter(defaultValue = "${project}", readonly = true)
private MavenProject project;
/**
* 是否显示详细信息
*/
@Parameter(property = "showDetail", defaultValue = "false")
private boolean showDetail;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
getLog().info("开始统计代码...");
CodeStat stat = new CodeStat();
stat.analyze(sourceDirectory.toPath());
getLog().info("====== 代码统计结果 ======");
getLog().info("Java文件数: " + stat.getJavaFileCount());
getLog().info("总行数: " + stat.getTotalLines());
getLog().info("代码行数: " + stat.getCodeLines());
getLog().info("注释行数: " + stat.getCommentLines());
getLog().info("空白行数: " + stat.getBlankLines());
if (showDetail) {
getLog().info("====== 文件详情 ======");
stat.getFileStats().forEach((file, s) -> {
getLog().info(file + ": " + s.getCodeLines() + "行代码");
});
}
}
/**
* 代码统计类
*/
static class CodeStat {
private int javaFileCount;
private int totalLines;
private int codeLines;
private int commentLines;
private int blankLines;
private Map fileStats = new HashMap<>();
public void analyze(Path directory) {
try {
Files.walk(directory)
.filter(p -> p.toString().endsWith(".java"))
.forEach(this::analyzeFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void analyzeFile(Path file) {
try {
javaFileCount++;
FileStat fileStat = new FileStat();
boolean inBlockComment = false;
for (String line : Files.readAllLines(file)) {
totalLines++;
String trimmed = line.trim();
if (trimmed.isEmpty()) {
blankLines++;
fileStat.blankLines++;
} else if (inBlockComment) {
commentLines++;
fileStat.commentLines++;
if (trimmed.contains("*/")) {
inBlockComment = false;
}
} else if (trimmed.startsWith("//")) {
commentLines++;
fileStat.commentLines++;
} else if (trimmed.startsWith("/*")) {
commentLines++;
fileStat.commentLines++;
if (!trimmed.contains("*/")) {
inBlockComment = true;
}
} else {
codeLines++;
fileStat.codeLines++;
}
}
fileStats.put(file.getFileName().toString(), fileStat);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
// getters...
}
static class FileStat {
int codeLines;
int commentLines;
int blankLines;
public int getCodeLines() {
return codeLines;
}
}
// getters...
}
插件POM配置
4.0.0
com.example.maven.plugins
code-stat-maven-plugin
1.0.0
maven-plugin
Code Stat Maven Plugin
org.apache.maven
maven-plugin-api
3.9.5
provided
org.apache.maven.plugin-tools
maven-plugin-annotations
3.10.2
provided
org.apache.maven.plugins
maven-plugin-plugin
3.10.2
code-stat
四、实战应用场景
场景一:Spring Boot项目POM模板
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.2.0
com.example
spring-boot-demo
1.0.0
Spring Boot Demo
17
3.5.5
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-validation
com.baomidou
mybatis-plus-boot-starter
${mybatis-plus.version}
com.mysql
mysql-connector-j
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
五、总结与最佳实践
5.1 最佳实践清单
- 版本管理
- 通过dependencyManagement统一版本。
- 利用BOM简化依赖管理。
- 定期更新依赖版本。
- 多模块设计
- 根据功能垂直拆分。
- 提取公共模块。
- 确保单向依赖,避免循环。
- 构建优化
- 合理配置跳过测试。
- 启用并行构建。
- 配置本地镜像加速。
- 规范约束
- 统一编码规范。
- 配置Checkstyle。
- 使用Formatter插件。
5.2 常用命令速查
# 清理构建
mvn clean# 编译
mvn compile# 打包
mvn package# 安装到本地仓库
mvn install# 部署到远程仓库
mvn deploy# 查看依赖树
mvn dependency:tree# 分析依赖
mvn dependency:analyze# 查看有效POM
mvn help:effective-pom# 更新依赖版本
mvn versions:display-dependency-updates# 更新插件版本
mvn versions:display-plugin-updates
5.3 常见问题
Q1: 依赖冲突如何解决?
- 利用dependency:tree分析。
- 通过exclusion排除冲突依赖。
- 在dependencyManagement中强制版本。
Q2: 如何加速构建?
- 配置阿里云镜像。
- 使用离线模式 `-o`。
- 并行构建 `-T 1C`。
Q3: 如何管理多环境配置?
- 使用Maven Profile。
- 配合Spring Boot Profile。
- 资源过滤动态注入。
参考资料
- 《Maven实战》
- Maven官方文档:maven.apache.org/
- Spring Boot Maven Plugin文档
- 《Maven权威指南》
六、思考与练习
思考题
- 基础题:Maven的依赖范围有哪些?它们分别作用于什么阶段?
- 进阶题:当项目中出现依赖冲突时,Maven是如何决策选择哪个版本的?请说明"最短路径优先"和"先声明优先"两种策略的区别。
- 实战题:如何设计一个多模块Maven项目?父子POM如何配置才能实现版本统一管理和模块间依赖?
编程练习
练习:创建一个多模块Maven项目,包含common(公共模块)、service(业务模块)、web(启动模块)三个子模块,实现模块间的依赖关系配置,并配置统一的版本管理和公共依赖。
章节关联
- 前置章节:Java基础、面向对象编程
- 后续章节:Gradle构建详解、依赖冲突解决
- 扩展阅读:《Maven实战》、《Maven权威指南》
本章完
相关文章
- Gemini下载怎么用?3个步骤搞定 06-04
- Gemini API密钥怎么申请?2026实测4种渠道对比 06-04
- 壹深圳app如何查看回放 06-04
- 我亲测了Gemini学生认证,全流程+踩坑记录 06-04
- Gemini 3.0使用教程 vs 4.0:3大区别与选择建议 06-04
- 干紫菜是紫色的炖汤后变成了绿色这是买到假紫菜了吗 小鸡宝宝考考你蚂蚁庄园3月9日答案 06-04