Maven 全套实战:从安装到多模块企业级构建
背景与价值
Maven 是 Java 生态事实标准构建工具(Ant 已老、Gradle 学习成本高)。核心价值:
- 依赖管理:自动下载 jar 及其传递依赖,避免版本冲突
- 标准化结构:
src/main/java、src/test/java 等约定优于配置 - 多模块管理:父子 POM 继承 +
dependencyManagement 统一版本 - 构建生命周期:
compile / test / package / install / deploy 一键式
本文按"安装 → 核心配置 → 多模块 → 实战坑"完整路径展开,基于 Maven 3.9.x 实测。
安装与配置
1. 下载解压
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # Linux
curl -O https://archive.apache.org/dist/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gz
mkdir -p /opt/maven
tar -zxvf apache-maven-3.9.6-bin.tar.gz -C /opt/maven
# 配置环境变量
export JAVA_HOME=/opt/java/jdk1.8.0_381
export MAVEN_HOME=/opt/maven
export PATH=.:$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$MAVEN_HOME/bin:$PATH
# 验证
mvn -version
# Apache Maven 3.9.6 (8c8575b0e1b8...)
# Java version: 1.8.0_381
|
2. 全局配置文件 ${maven_home}/conf/settings.xml
settings.xml 集中管理仓库镜像、代理、profile、服务器认证等全局配置,避免每个项目单独配。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| <?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0">
<!-- 本地仓库路径(默认 ${user.home}/.m2/repository) -->
<!--<localRepository>/path/to/local/repo</localRepository>-->
<!-- 离线模式(无法联网时) -->
<!--<offline>false</offline>-->
<!-- 代理(公司内网访问外网 Maven 中央仓库时) -->
<proxies>
<proxy>
<id>myproxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy.example.com</host>
<port>8080</port>
<username>proxyuser</username>
<password>{{PROXY_PASSWORD}}</password>
<nonProxyHosts>*.google.com|ibiblio.org</nonProxyHosts>
</proxy>
</proxies>
<!-- 服务器认证(部署到 Nexus / 私库时用) -->
<servers>
<server>
<id>nexus-releases</id>
<username>{{NEXUS_USER}}</username>
<password>{{NEXUS_PASSWORD}}</password>
</server>
</servers>
<!-- 镜像(关键:阿里云加速国内下载) -->
<mirrors>
<mirror>
<id>aliyun-public</id>
<name>阿里云 Maven 公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<!-- 多环境 Profile -->
<profiles>
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</profile>
</profiles>
</settings>
|
3. 阿里云镜像配置(关键)
国内访问 Maven 中央仓库(repo1.maven.org)经常超时,建议配置阿里云镜像:
| 仓库类型 | 阿里云地址 |
|---|
| 公共仓库 | https://maven.aliyun.com/repository/public |
| Google | https://maven.aliyun.com/repository/google |
| Spring | https://maven.aliyun.com/repository/spring |
| Apache Snapshots | https://maven.aliyun.com/repository/apache-snapshots |
配置示例(settings.xml 镜像):
1
2
3
4
5
6
| <mirror>
<id>aliyun-spring</id>
<name>阿里云 Spring 仓库</name>
<url>https://maven.aliyun.com/repository/spring</url>
<mirrorOf>spring-milestones,spring-snapshots</mirrorOf>
</mirror>
|
核心概念
1. 坐标(GAV)
每个 Maven 构件由三要素唯一定位:
1
2
3
4
5
| <dependency>
<groupId>org.springframework.boot</groupId> <!-- 组织 -->
<artifactId>spring-boot-starter-web</artifactId> <!-- 项目 -->
<version>3.2.0</version> <!-- 版本 -->
</dependency>
|
2. 仓库类型
| 类型 | 位置 | 用途 |
|---|
| 本地仓库 | ~/.m2/repository/ | 已下载的依赖 |
| 中央仓库 | repo1.maven.org | Maven 官方仓库(默认) |
| 私服 | Nexus / Artifactory | 公司内网,缓存 + 部署 |
| 镜像仓库 | 阿里云 / 华为云 | 中央仓库的国内镜像 |
3. 依赖范围(Scope)
| Scope | 编译 | 测试 | 运行时 | 例子 |
|---|
compile(默认) | ✅ | ✅ | ✅ | spring-core |
provided | ✅ | ✅ | ❌ | servlet-api(容器提供) |
runtime | ❌ | ✅ | ✅ | JDBC 驱动 |
test | ❌ | ✅ | ❌ | JUnit |
system | ✅ | ✅ | ❌ | 引用本地 jar(不推荐) |
4. 生命周期阶段
1
2
3
4
5
6
| mvn clean # 清理 target/
mvn compile # 编译 main
mvn test # 编译并运行测试
mvn package # 打包成 jar/war
mvn install # 安装到本地仓库(供其他模块引用)
mvn deploy # 部署到远程私服
|
多模块项目(企业级核心)
1. 父 POM 约定
1
2
3
4
5
6
7
8
9
10
11
| my-project/ # 父项目根目录
├── pom.xml # 父 POM(packaging=pom)
├── my-app/ # 主应用模块
│ ├── pom.xml
│ └── src/
├── my-common/ # 公共工具模块
│ ├── pom.xml
│ └── src/
└── my-api/ # API 定义模块
├── pom.xml
└── src/
|
2. 父 POM 完整模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<!-- 继承 Spring Boot Starter Parent(统一版本管理) -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.14</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>my-project</name>
<!-- 子模块清单 -->
<modules>
<module>my-common</module>
<module>my-api</module>
<module>my-app</module>
</modules>
<!-- 统一版本管理(子模块引用时不需要写版本号) -->
<dependencyManagement>
<dependencies>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 项目内部模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 公共依赖(所有子模块都会继承) -->
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- 统一属性 -->
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2021.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
</properties>
<!-- 多环境 Profile -->
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<profile.name>dev</profile.name>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<profile.name>test</profile.name>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<profile.name>prod</profile.name>
</properties>
</profile>
</profiles>
</project>
|
3. 子模块 POM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| <?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>my-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<!-- 不需要写版本号(父 dependencyManagement 已管理) -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-common</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
|
常用命令
| 命令 | 作用 |
|---|
mvn clean | 清理 target 目录 |
mvn compile | 编译主代码 |
mvn test | 运行单元测试 |
mvn package -DskipTests | 打包跳过测试 |
mvn dependency:tree | 树形展示依赖 |
mvn dependency:tree -Dincludes=commons-logging | 过滤特定依赖 |
mvn help:effective-pom | 查看完整 POM(合并父子) |
mvn -Pprod clean package | 激活 prod profile 打包 |
mvn -pl my-app -am package | 只构建 my-app 及其依赖模块 |
实战坑
1. 依赖冲突(NoClassDefFoundError / NoSuchMethodError)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| # 查看依赖树
mvn dependency:tree -Dverbose
# 排除传递依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>my-lib</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
|
2. JAR 包冲突定位
1
2
3
4
5
6
| # 找哪个 jar 引入的
mvn dependency:tree -Dincludes=com.google.guava:guava
# 输出:
# [INFO] +- com.example:my-lib:jar:1.0:compile
# [INFO] | \- com.google.guava:guava:jar:30.0-jre:compile ← 这里
|
3. SNAPSHOT 版本不稳定
1.0.0-SNAPSHOT 表示"开发中快照",Maven 默认每次构建都拉取最新。生产环境应锁定 release 版本。
4. mvn package 跳过测试
1
2
3
4
5
6
7
8
9
10
11
| # 方式 1:命令行参数
mvn package -DskipTests
# 方式 2:surefire 插件配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
|
5. 配置中心化 vs 分散
- 统一管理:父 POM
dependencyManagement 集中版本 - 覆盖:子模块可显式覆盖(极少数情况)
- 避免:每个子模块独立写版本号(升级时全项目都要改)
Maven Wrapper(推荐)
mvnw 是项目自带的 Maven 包装脚本,避免开发者本地 Maven 版本不一致:
1
2
3
4
5
6
7
8
9
| # 生成 wrapper(项目根目录执行一次)
mvn -N io.takari:maven:0.7.7:wrapper -Dmaven=3.9.6
# 提交到 Git
git add mvnw mvnw.cmd .mvn/
git commit -m "build: 添加 Maven Wrapper"
# 团队成员执行(无需安装 Maven)
./mvnw clean package
|
私服搭建(Nexus 3.x)
1
2
3
4
5
6
| # Docker 一键启动
docker run -d \
-p 8081:8081 \
-v /data/nexus-data:/nexus-data \
--name nexus \
sonatype/nexus3:3.64.0
|
部署到 Nexus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| <!-- 项目 pom.xml -->
<distributionManagement>
<repository>
<id>nexus-releases</id> <!-- 对应 settings.xml server id -->
<url>http://{{NEXUS_HOST}}:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://{{NEXUS_HOST}}:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
</plugin>
</plugins>
</build>
|
前置知识与下一步
前置:
- Java 基础语法、IDE 使用
- 基本的命令行操作
- 了解 Spring Boot 项目结构
下一步:
- 复杂构建用 Maven Profile + Resource Filtering 实现多环境打包
- 配合 Dockerfile + CI/CD 一键出镜像
- 巨型项目切分用 Maven 多仓库 + 微服务,避免单仓库超大
小结
Maven 3.9 + 阿里云镜像 + 标准 settings.xml 是企业 Java 项目的"开箱即用"组合。多模块项目靠父 POM dependencyManagement 统一版本 + 子 POM 引用简化,是避免"依赖版本地狱"的关键。Maven Wrapper 解决了团队成员本地 Maven 版本不一致的痛点。Nexus 私服是企业内网依赖缓存 + 内部 jar 部署的标配。
2024+ 视角:Maven 4 预览 + Gradle 8 对比
Maven 4.0 关键变化(2024 仍在预发布)
- POM 结构化:XML → 仍是 XML,但解析器重写(Lexical 三遍解析),速度 +30%
- 多语言项目支持:原 Maven 只管 Java,Maven 4 开始支持 JS / Python / Rust 子项目
dependencyManagement 路径表达式:支持 ${groupId:artifactId:type:version} 直接引用父项目- CI 集成深度增强:
mvn verify 输出 SBOM(软件物料清单)——合规审计直接用 - MVN Daemon(实验):常驻进程 + 增量编译,类似 Gradle Daemon
Maven 4 升级路径
1
2
3
4
5
6
7
8
| <!-- pom.xml 顶部 -->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
...
</project>
|
主要差异:
- POM modelVersion 不变(仍是 4.0.0)
- 升级命令:
mvn -P maven-4-upgrade verify(Maven 4 自带) - 大部分插件需升级到 4.x 版本
Gradle 8.x 与 Maven 4 的 2024+ 对比
| 维度 | Maven 4 | Gradle 8.x |
|---|
| 构建速度 | 较慢(提升 30%) | 快 2-10 倍(增量 + 守护进程) |
| 配置语言 | XML | Kotlin DSL / Groovy |
| 增量构建 | 需 mvn incremental | 原生支持 |
| 多语言 | 实验 | Kotlin Multiplatform / Android |
| 生态稳定性 | 25 年沉淀,文档全 | 较新,插件质量参差 |
| 学习曲线 | 低(约定优于配置) | 中(DSL 学习) |
| 企业 Java 占比 | 70%+ | 15% |
选型建议:
- 新项目(Kotlin / Android / 复杂构建):Gradle 8.x
- 传统 Spring / 金融 / 政府:Maven 仍是首选——团队上手快、CI 配置简单
- Kotlin Multiplatform / 跨平台:必须 Gradle
镜像配置的 2024+ 演进
阿里云 2023 年起对 Maven 中央仓库做了全量同步,但 2024 之后新增了:
- 华为云镜像:
https://repo.huaweicloud.com/repository/maven/ - 腾讯云镜像:
https://mirrors.cloud.tencent.com/nexus/repository/maven-public/ - 中国移动云镜像:
https://mirrors.cmecloud.cn/repository/maven/
1
2
3
4
5
6
7
| <mirrors>
<mirror>
<id>huawei-cloud</id>
<url>https://repo.huaweicloud.com/repository/maven/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
|
dependencyManagement 2024+ 进阶
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| <!-- BOM 引用(Bill of Materials)-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2023.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
|
Maven Wrapper 的 2024+ 变化
1
2
3
4
5
| # 旧版(Takari wrapper)
mvn -N io.takari:maven:0.7.7:wrapper -Dmaven=3.9.6
# 新版(Maven 官方 wrapper 3.2+)
mvn wrapper:wrapper -Dmaven=3.9.9
|
新版 wrapper 由 Maven 官方维护,不需要 Takari 仓库。
依赖冲突排查的 2024+ 新工具
1
2
3
4
5
6
7
8
9
10
11
12
| # 1. mvn dependency:tree(老牌)
mvn dependency:tree -Dverbose -Dincludes=commons-logging:commons-logging
# 2. maven-dependency-plugin 3.6+:dependency:analyze
mvn dependency:analyze
# 3. Enforcer 插件:禁止某些依赖
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
</plugin>
|
实战坑(2024+)
- Spring Boot 3.x 必须 JDK 17+——Maven 3.8.x 之前的版本不支持
--add-opens,需用 3.9.x - Maven Central 在 2024-06 调整了 HTTPS 证书链——老 Maven 版本(< 3.6.3)需升级
- Nexus 3.64+ 强制 HTTPS——HTTP 私服要升级或保留 HTTP 白名单
- JCenter 2022 已停止服务——所有
jcenter() 引用要改 mavenCentral()
2024+ 推荐组合
1
2
3
4
5
6
7
8
9
10
11
| 企业 Java 项目(Spring Boot 3.x)
├── Maven 3.9.x / Maven 4.0(2024+)
├── 阿里云镜像 + settings.xml
├── Maven Wrapper 3.2+
├── spring-boot-starter-parent 3.4.x
├── spring-cloud-dependencies 2024.0.x BOM
├── spring-cloud-alibaba-dependencies 2023.0.x BOM
├── 父 POM dependencyManagement 统一版本
├── 子 POM 引用无版本号
├── Nexus 3.64+ 私服(maven-releases + maven-snapshots)
└── mvn -Pprod clean package + Jib 打 Docker 镜像
|