Maven学习笔记
Maven学习笔记
LynxFrostMaven介绍
Maven 是一个 项目管理与构建自动化工具
Maven 解决了软件构建的两方面问题:
- 一是软件是如何构建的。
- 二是软件的依赖关系。
Maven 的核心功能包括:
- 项目构建(编译、测试、打包、部署)
- 依赖管理(自动下载和管理第三方库)
- 标准化项目结构(约定优于配置)
- 插件扩展(支持自定义构建流程)
优势:
- 减少配置:约定优于配置,减少
build.xml(Ant)这样的手动配置。 - 依赖自动管理:只需声明依赖,Maven 自动下载并处理冲突。
- 跨平台:基于 Java,可在 Windows、Linux、macOS 上运行。
- 与 IDE 集成:Eclipse、IntelliJ IDEA、VS Code 都支持 Maven。
Maven 下载
Maven 下载地址:http://maven.apache.org/download.cgi
不同平台下载对应的包:
| 系统 | 包名 |
|---|---|
| Windows | apache-maven-3.3.9-bin.zip |
| Linux | apache-maven-3.3.9-bin.tar.gz |
| Mac | apache-maven-3.3.9-bin.tar.gz |
新建系统变量 MAVEN_HOME,变量值:E:\Maven\apache-maven-3.3.9
编辑系统变量 Path,添加变量值:;%MAVEN_HOME%\bin
配置 Maven 本地仓库
Maven 默认从远程仓库下载依赖,并存储在本地:
默认本地仓库路径:
- Windows:
C:\Users\<用户名>\.m2\repository - Linux/macOS:
~/.m2/repository
修改仓库位置(可选):
在 MAVEN_HOME/conf/settings.xml 中修改:
<localRepository>/path/to/your/repo</localRepository> |
创建 Maven 项目
使用 Maven 创建项目
运行以下命令生成标准 Java 项目:
mvn archetype:generate \ |
参数说明:
| 参数 | 说明 |
|---|---|
-DgroupId |
组织名(如公司域名倒写) |
-DartifactId |
项目名称(会成为项目文件夹名) |
-DarchetypeArtifactId |
使用的模板(quickstart 是基础 Java 项目) |
-DinteractiveMode=false |
非交互模式(避免手动确认) |
这会生成一个标准 Maven 项目结构:
my-first-app/ |
源代码结构
| 目录 | 作用 |
|---|---|
src/main/java |
主 Java 源代码 |
src/main/resources |
配置文件(如 application.properties) |
src/test/java |
测试代码 |
src/test/resources |
测试资源文件 |
解读 pom.xml
生成的 pom.xml 示例:
<project> |
常用 Maven 命令
| 命令 | 作用 |
|---|---|
mvn compile |
编译源代码 |
mvn test |
运行测试 |
mvn package |
打包(生成 .jar 文件) |
mvn install |
安装到本地仓库(供其他项目依赖) |
mvn clean |
清理 target 目录 |
常见问题
依赖下载失败
原因:网络问题或仓库不可用。
解决方案:
检查网络连接。
配置国内镜像仓库(如阿里云):
<!-- 在 settings.xml 或 pom.xml 中配置 --> |
阿里云仓库介绍:https://developer.aliyun.com/mvn/guide。
编译版本问题
错误:javac: invalid target release: 11
解决方案:在 pom.xml 中指定 Java 版本:
<properties> |
Maven POM
POM ( Project Object Model,项目对象模型 ) 是 Maven 的核心配置文件,采用 XML 格式,默认命名为 pom.xml。
POM 是 Maven 工程的基本工作单元,是一个 XML 文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖,等等。
执行任务或目标时,Maven 会在当前目录中查找 POM,获取所需的配置信息,然后执行目标。
POM 标签大全详解
以下是对 pom.xml 中所有重要标签的分类说明,涵盖 项目信息、依赖管理、构建配置、环境设置 等核心内容。
所有 POM 文件必须包含的标签: modelVersion、groupId、artifactId 和 version。
| 标签 | 类别 | 说明 | 示例/可选值 | 是否必需 |
|---|---|---|---|---|
| 基础信息 | ||||
<modelVersion> |
项目结构 | POM模型版本 | 4.0.0 |
是 |
<groupId> |
坐标 | 组织标识(反向域名) | com.example |
是 |
<artifactId> |
坐标 | 项目名称 | my-project |
是 |
<version> |
坐标 | 项目版本 | 1.0.0-SNAPSHOT |
是 |
<packaging> |
项目类型 | 打包格式 | jar/war/pom |
否(默认jar) |
<name> |
元信息 | 项目显示名称 | My Application |
否 |
<description> |
元信息 | 项目描述 | A demo project |
否 |
<url> |
元信息 | 项目主页URL | https://example.com |
否 |
| 依赖管理 | ||||
<dependencies> |
依赖 | 依赖列表容器 | 包含多个<dependency> |
否 |
<dependency> |
依赖 | 单个依赖定义 | 包含groupId等子标签 |
可选 |
<scope> |
依赖 | 依赖作用域 | compile/test/provided/runtime |
否(默认compile) |
<optional> |
依赖 | 是否可选依赖 | true/false |
否(默认false) |
<exclusions> |
依赖 | 排除传递性依赖 | 包含<exclusion>列表 |
否 |
| 构建配置 | ||||
<build> |
构建 | 构建配置容器 | 包含插件/资源等配置 | 否 |
<plugins> |
构建 | 插件列表容器 | 包含多个<plugin> |
否 |
<plugin> |
构建 | 单个插件定义 | 需指定groupId和artifactId |
可选 |
<resources> |
构建 | 资源文件配置 | 定义<resource>路径 |
否 |
<testResources> |
构建 | 测试资源文件配置 | 类似<resources> |
否 |
<finalName> |
构建 | 最终打包文件名 | my-app |
否 |
| 环境配置 | ||||
<properties> |
配置 | 自定义变量容器 | 定义键值对 | 否 |
<java.version> |
属性 | Java版本变量 | 11/17等 |
否 |
<repositories> |
仓库 | 自定义远程仓库列表 | 包含<repository> |
否 |
<pluginRepositories> |
仓库 | 自定义插件仓库 | 类似<repositories> |
否 |
| 多模块管理 | ||||
<modules> |
模块 | 子模块列表 | 包含多个<module> |
聚合项目需要 |
<parent> |
继承 | 父POM引用 | 需指定父项目坐标 | 继承项目需要 |
<dependencyManagement> |
依赖 | 统一管理依赖版本 | 定义版本但不引入 | 否 |
<profiles> |
配置 | 环境profile容器 | 定义不同环境配置 | 否 |
| 其他信息 | ||||
<licenses> |
法律 | 许可证信息 | 包含<license> |
否 |
<developers> |
人员 | 开发者列表 | 包含<developer> |
否 |
<contributors> |
人员 | 贡献者列表 | 类似<developers> |
否 |
<issueManagement> |
管理 | 问题跟踪系统 | 定义issue系统URL | 否 |
Maven 构建生命周期
Maven 构建生命周期定义了一个项目构建跟发布的过程,包含三个标准生命周期:
- clean:清理项目
- default(或 build):核心构建流程
- site:生成项目文档
1、Clean 生命周期:
- clean:删除目标目录中的编译输出文件。这通常是在构建之前执行的,以确保项目从一个干净的状态开始。
2、Default 生命周期(也称为 Build 生命周期):
- validate:验证项目的正确性,例如检查项目的版本是否正确。
- compile:编译项目的源代码。
- test:运行项目的单元测试。
- package:将编译后的代码打包成可分发的格式,例如 JAR 或 WAR。
- verify:对项目进行额外的检查以确保质量。
- install:将项目的构建结果安装到本地 Maven 仓库中,以供其他项目使用。
- deploy:将项目的构建结果复制到远程仓库,以供其他开发人员或团队使用。
3、Site 生命周期:
- site:生成项目文档和站点信息。
- deploy-site:将生成的站点信息发布到远程服务器,以便共享项目文档。
Maven 构建配置文件
构建配置文件是一系列的配置项的值,可以用来设置或者覆盖 Maven 构建默认值。
使用构建配置文件,你可以为不同的环境,比如说生产环境(Production)和开发(Development)环境,定制构建方式。
配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。配置文件在构建时修改 POM,并且用来给参数设定不同的目标环境(比如说,开发(Development)、测试(Testing)和生产环境(Production)中数据库服务器的地址)。
构建配置文件的类型
构建配置文件大体上有三种类型:
| 类型 | 在哪定义 |
|---|---|
| 项目级(Per Project) | 定义在项目的POM文件pom.xml中 |
| 用户级 (Per User) | 定义在Maven的设置xml文件中 (%USER_HOME%/.m2/settings.xml) |
| 全局(Global) | 定义在 Maven 全局的设置 xml 文件中 (%M2_HOME%/conf/settings.xml) |
Maven 常用命令
Maven 命令遵循以下模式:
mvn [选项] [生命周期阶段] [目标] |
Maven 三大生命周期:
clean、default(构建)、site
一、基础生命周期命令
| 命令 | 作用 |
|---|---|
mvn -v |
查看 Maven、JDK 版本 |
mvn clean |
清理,删除 target 目录 |
mvn validate |
校验项目结构、pom 是否合法 |
mvn compile |
编译主代码,输出到 target/classes |
mvn test-compile |
编译测试代码 |
mvn test |
执行单元测试 |
mvn package |
打包(jar/war) |
mvn verify |
执行集成测试,校验包 |
mvn install |
打包后安装到本地仓库 |
mvn deploy |
上传包到远程私服 |
生命周期阶段是顺序执行:执行后面阶段会自动执行前面所有阶段。 例:
mvn package→ 自动执行 validate → compile → test-compile → test → package
二、依赖管理
# 打印依赖树,排查依赖冲突 |
三、测试相关
# 执行全部测试 |
四、多模块项目
# -pl:指定模块(只构建service模块) |
五、插件 & POM 查看
# 查看最终生效的完整 pom(合并父pom、profile) |
六、创建项目
# 创建普通Java项目 |
七、高频组合命令
# 清理 + 编译 + 测试 + 安装到本地仓库 |
八、高级参数
# 离线模式,不访问远程仓库,只用本地缓存 |
九、Maven Site 文档
# 生成项目站点文档 |
Maven 依赖机制
一、核心作用
Maven 自动管理第三方 jar,自动下载依赖、自动引入传递依赖,不用手动拷贝 jar 包。
查找顺序:本地仓库 → 远程私服(如果配置) → Maven 中央仓库
二、Maven 坐标
groupId + artifactId + version,三者定位一个 jar
<dependency> |
三、依赖 Scope 依赖范围
Scope 控制依赖在编译、测试、运行哪个阶段生效,同时影响传递依赖和打包。
| scope | 生效阶段 | 是否打入包 | 说明 |
|---|---|---|---|
| compile(默认) | 编译、测试、运行 | ✅ | 核心业务依赖,会传递 |
| provided | 编译、测试 | ❌ | 运行时容器 / JDK 提供(servlet-api) |
| runtime | 测试、运行 | ✅ | 编译不需要,运行需要(jdbc 驱动) |
| test | 仅测试 | ❌ | 单元测试,不传递(junit) |
| system | 编译、测试 | ❌ | 指定本地 jar 路径,不推荐使用 |
传递规则:只有
compile、runtime会传递;provided、test不会向下传递。
四、传递依赖(Transitive Dependency)
A 依赖 B,B 依赖 C → Maven 自动把 C 引入 A 项目。 缺点:容易带来依赖冲突
解决冲突:依赖调解(Dependency Mediation)
两条核心规则:
- 最短路径优先:依赖树路径短的版本胜出
- 路径长度相同:先声明优先,pom 里靠前的依赖版本生效
排查冲突命令:
mvn dependency:tree
五、排除传递依赖 exclusions
不想引入某个传递依赖时使用,不需要写 version
<dependency> |
六、可选依赖 optional
<optional>true</optional> |
当前项目依赖这个 jar,但不会传递给依赖自己的上层项目。 区别:exclusions 是主动排除;optional 是声明不传递。
七、dependencyManagement
只统一版本声明,不会自动引入依赖! 父工程 pom:
<dependencyManagement> |
子模块引用时,只需要 groupId、artifactId,省略 version
<dependencies> |
BOM(Bill of Materials)导入
SpringBoot 大量使用,一次性导入一组依赖版本管理
<dependencyManagement> |
importscope:只能放在 dependencyManagement 里,导入其他 pom 的版本管理。
八、Maven 仓库
- 本地仓库:
~/.m2/repository,本机缓存 jar - 远程仓库
- 中央仓库:Maven 官方默认公共仓库
- 私服:企业内部 Nexus 仓库(内网,存放公司私有 jar + 代理中央仓库)
仓库配置:
settings.xml(用户目录 /maven 安装目录)、pom.xml 均可配置 repositories
九、依赖相关常用命令
# 查看依赖树,定位冲突 |
十、最佳实践
- 不要使用
LATEST/RELEASE动态版本,版本固定,保证构建可复现 - 多模块项目统一使用
dependencyManagement+ BOM 管理版本 - 出现版本冲突:
dependency:tree定位,使用exclusions排除 - 谨慎使用
systemscope 和 optional - 定期执行
dependency:analyze清理无用依赖
Maven 多模块项目管理
一、概念
Maven 多模块项目由父项目(parent)和多个子模块(submodule)组成。父项目本身不写业务代码,主要负责统一管理版本、依赖、插件,子模块是实际业务代码。
父项目打包类型必须是:
<packaging>pom</packaging>
目录结构
parent-project/ # 父工程 |
二、核心配置
1. 父工程 pom.xml
<project> |
2. 子模块 pom.xml(继承父工程)
<project> |
3. 模块之间相互依赖
例如 module-service 依赖 module-common:
<dependencies> |
区分两个关键点:
<dependencyManagement>:只锁定版本,不会自动引入依赖,子模块想用需要自己在 dependencies 声明- 父工程直接写在
<dependencies>:所有子模块全部自动继承该依赖
三、多模块构建命令
在父工程目录执行:
# 构建全部子模块,Maven自动根据模块依赖顺序构建 |
-pl=projects list:指定模块列表,逗号分隔多个模块-am=also-make:构建当前模块,同时构建它依赖的模块-rf=resume-from:从指定模块恢复构建
Maven Reactor:负责多模块项目,自动计算模块构建顺序。
四、多模块项目优势
- 职责拆分:大型项目分层拆分(common、dao、service、web),便于团队协作
- 代码复用:公共代码抽成 common 模块,其他模块引用
- 统一管理:统一版本、依赖、插件配置
- 按需构建:可以只构建改动模块,提升构建速度
五、常见问题
1. 循环依赖(模块 A 依赖 B,B 依赖 A)
Maven 构建直接报错,不允许模块循环依赖 解决:提取公共代码到第三个公共模块,解耦。
2. 构建顺序问题
Maven Reactor 自动分析模块依赖关系决定构建顺序;如果依赖关系复杂识别错误,可以显式调整。
3. dependencyManagement 和父 dependencies 容易混淆
- dependencyManagement:版本锁定,按需引入,推荐大型项目使用
- 父 dependencies:强制全部子模块继承依赖,容易引入多余 jar,慎用
六、最佳实践
- 父工程只用
dependencyManagement统一版本,尽量不要在父 dependencies 写大量依赖,避免依赖泛滥 - 公共工具类抽成独立 common 模块
- 禁止模块之间循环依赖
- 使用
-pl -am按需构建,提高开发效率 - 统一版本号,使用
${project.version}引用当前项目版本
Maven 插件
一、核心概念
Maven 本身只是执行框架,所有实际工作全部由插件 (plugin)完成。
- 插件(Plugin):可扩展组件,一个插件包含多个目标(Goal)
- 目标 Goal:插件里最小执行单元,代表一个具体任务
- 生命周期 Phase:构建阶段,只是一个 “钩子 / 接口”,本身不干活,需要绑定插件目标来执行
语法:
mvn 插件前缀:目标名 |
插件与生命周期关系
Maven 三大生命周期:clean、default、site 每个生命周期由一系列 phase(阶段)组成。 Maven内置绑定:phase 默认绑定好对应的插件 goal。 例: mvn compile → 触发 default 生命周期 compile 阶段 → 自动调用 maven-compiler-plugin:compile
两种执行方式区别:
mvn compile:执行生命周期阶段,自动执行前面所有前置阶段mvn compiler:compile:直接调用插件目标,不会触发生命周期,只执行这个目标
二、插件坐标
插件和依赖一样,使用 groupId + artifactId + version 唯一标识 官方插件 groupId 固定:org.apache.maven.plugins 示例:
<plugin> |
三、插件目标绑定(2 种方式)
1. 内置绑定(Maven 自带,无需配置)
| 生命周期阶段 | 绑定插件目标 |
|---|---|
| compile | maven-compiler-plugin:compile |
| test | maven-surefire-plugin:test |
| package | maven-jar-plugin:jar / maven-war-plugin:war |
| clean | maven-clean-plugin:clean |
2. 自定义绑定(pom.xml 手动配置)
通过 <executions> 将插件目标绑定到指定生命周期阶段,可以多次执行同一个插件不同任务
<build> |
<configuration>:配置插件参数<executions>:可以配置多组执行,每组可指定不同 phase、goal
四、常用 Maven 官方插件
maven-compiler-plugin:编译 Java 代码,目标:compile、testCompile
配置 source/target 指定 JDK 版本
maven-resources-plugin:复制资源文件(resources、testResources)
maven-surefire-plugin:执行单元测试(
test目标)maven-failsafe-plugin:执行集成测试(integration-test)
maven-jar-plugin:打包 jar,可配置 mainClass 指定程序入口
maven-war-plugin:打包 war 包
maven-assembly-plugin:自定义打包(打包所有依赖,生成可执行完整包)
maven-clean-plugin:clean 阶段,删除 target 目录
maven-install-plugin:install,安装到本地仓库
maven-deploy-plugin:deploy,上传到远程私服
示例:指定 JDK 版本 compiler 插件
<plugin> |
五、插件两大分类
- Build plugins(构建插件):在构建过程执行,配置在
<build><plugins> - Reporting plugins(报告插件):生成站点文档报告,配置在
<reporting>
六、Mojo
Mojo = Maven Plain Old Java Object
插件目标对应的 Java 类,一个 Mojo 对应一个 Goal。 自定义 Mojo 需要继承
AbstractMojo,重写execute()方法,加上@Mojo注解。
|
七、插件调用方式
- 生命周期触发(推荐)
mvn compile |
- 直接调用插件目标
mvn compiler:compile |
- 命令行传参覆盖插件配置
mvn compiler:compile -Dmaven.compiler.source=11 |
Maven Archetype(原型 / 项目模板)
一、什么是 Archetype
archetype 是 Maven 的插件,中文叫原型,本质就是项目模板。 作用:一键生成一套标准化的 Maven 目录结构 + 基础 pom.xml + 示例代码,不用手动建包、建文件夹。
命令:
mvn archetype:generate,archetype:generate 是 archetype 插件的目标 goal。
二、内置常用原型
- maven-archetype-quickstart:普通 Java 项目(jar 包,最常用)
- maven-archetype-webapp:Java Web 项目(war 包,带 web.xml)
- 还有很多第三方原型:spring-boot-archetype 等
三、两种创建方式
方式 1:交互式(手动选择,直接执行)
mvn archetype:generate |
执行后会交互式一步步输入:
- 选择原型编号
- 选择原型版本
- 填写
groupId、artifactId、version、package - 确认信息,输入 Y,自动生成项目
方式 2:非交互式(脚本化,一次性传参,推荐)
# 普通Java项目 quickstart |
参数说明:
-DinteractiveMode=false:关闭交互,直接创建,不需要手动输入archetypeArtifactId:指定原型模板名称
四、quickstart 生成的标准目录结构
health/ |
自动生成的 pom.xml:
- packaging 默认
jar - 默认引入 junit 测试依赖(scope=test)
五、自定义 Archetype
可以自己制作 archetype 模板,把公司统一项目结构、pom 配置、工具类封装成自定义原型,团队所有人统一项目脚手架。
- 先做好一个参考项目
- 使用
mvn archetype:create-from-project基于现有项目生成原型 - install 到本地仓库,之后就可以用自定义 archetype 创建项目
Maven SNAPSHOT
一、什么是 SNAPSHOT
SNAPSHOT 是快照版本,代表开发中、尚未正式发布的版本。版本号后缀带上 -SNAPSHOT,例如 1.0-SNAPSHOT。
作用:多团队并行开发时,一个模块代码频繁迭代,其他模块可以持续拿到最新开发版,不用每次手动升级版本号。
二、快照版本 vs 正式版本(Release)
| 类型 | 示例 | 拉取逻辑 | 使用场景 |
|---|---|---|---|
| SNAPSHOT(快照) | 1.0-SNAPSHOT | Maven 构建时会去远程仓库检查是否有更新;本地缓存有快照,也可能拉取新版本 | 开发阶段,模块间联调 |
| Release(正式版) | 1.0 | 一旦下载到本地仓库,不会再次从远程拉取,版本固定不变 | 上线、稳定发布,版本不可修改 |
原理:私服上的 SNAPSHOT 包会自动带上时间戳,例如
data-service-1.0-20261007.083000-1.jar,Maven 识别时间戳获取最新快照。
三、核心参数 -U(—update-snapshots)
默认情况下 Maven 对快照有缓存策略,不一定每次构建都强制拉取最新。 -U 强制 Maven 去远程仓库更新 SNAPSHOT 依赖(面试高频)
mvn clean install -U |
四、使用示例
被依赖模块(data-service,快照)
<version>1.0-SNAPSHOT</version> |
每次代码提交,执行 mvn deploy 上传到私服,版本号不用改,私服自动覆盖 / 生成带时间戳的快照包。
依赖方模块(app-ui)引用快照
<dependency> |
app-ui 团队构建时,Maven 会尝试拉取私服最新的 1.0-SNAPSHOT。
五、SNAPSHOT 优缺点
优点
- 多团队并行开发,联调方便,不用频繁修改 pom 版本号
- 持续获取最新开发代码,适合开发阶段
缺点
- 构建结果不可复现:每次构建拿到的快照包可能不一样,同一个 pom 可能打包出不同产物
- 私服存储压力大,快照包会不断累积
- 生产环境严禁使用 SNAPSHOT,生产环境必须使用 Release 正式版本
六、最佳实践
- 开发环境:模块联调使用 SNAPSHOT;
- 测试、生产环境:全部使用 Release 正式版本,禁止快照;
- 发布上线前,要把版本去掉
-SNAPSHOT,升级为正式版本; - 拉取最新快照依赖,构建命令带上
-U; - 私服一般会配置快照包自动清理策略,防止磁盘占满。
Maven 自动化构建
一、什么是 Maven 自动化构建
场景:多个项目存在依赖关系。当底层公共模块(bus-core-api)代码更新构建完成后,自动触发依赖它的上层项目(app-web-ui、app-desktop-ui)进行构建,保证上层项目使用最新的依赖包。
结合 SNAPSHOT 快照一起使用:底层模块发布快照,上层项目构建自动拉取最新快照。
二、两种实现方案
方案 1:Maven 插件方式(maven-invoker-plugin)
利用 maven-invoker-plugin 插件,在当前项目构建完成后,自动调用其他项目的 pom 执行构建。 在底层项目 bus-core-api 的 pom.xml 配置插件:
<build> |
执行命令:
mvn clean package -U |
执行流程:
- 构建 bus-core-api
- bus-core-api 构建成功后,插件自动执行 app-web-ui 的构建
- app-web-ui 构建成功后,再执行 app-desktop-ui 的构建
优点:纯 Maven 实现,不需要额外服务
缺点:新增依赖项目,需要修改底层模块 pom,维护麻烦;项目多了 pom 臃肿。
方案 2:CI 持续集成服务器(推荐,企业主流)
代表工具:Hudson(老)、Jenkins、GitLab CI、GitHub Actions 等。 原理:
- 代码提交到 Git/SVN,触发 CI 服务器构建底层项目 bus-core-api
- bus-core-api 构建成功,自动触发下游依赖项目 app-web-ui、app-desktop-ui 构建
- CI 自动拉取最新 SNAPSHOT 依赖,完成构建
优点:
- 不用修改任何项目 pom.xml
- 新增下游项目,只需要在 CI 页面配置任务依赖关系
支持流水线、邮件通知、失败告警、多环境发布
缺点:需要单独部署维护 CI 服务
企业实际开发一般优先使用 CI 流水线,很少用 maven-invoker-plugin。
三、和 SNAPSHOT 的关系
自动化构建 + SNAPSHOT 快照配合使用: 底层模块更新,deploy 上传最新快照到私服;然后自动触发上层项目构建,上层项目构建时通过 -U 拉取最新快照,完成联调验证。
Maven 依赖管理
一、核心概念:传递性依赖
A 依赖 B,B 依赖 C;当项目引入 A,Maven 自动把 B、C 全部引入,这就是传递依赖。 只需要在 pom 写直接依赖,Maven 自动解析整个依赖树,不用手动写所有底层 jar。
缺点:依赖树膨胀,容易出现版本冲突。Maven 提供一套机制管控传递依赖。
二、Maven 处理依赖冲突:依赖调节
- 最短路径优先原则:依赖在依赖树中的路径越短,版本优先被选中。
- 路径深度相同时,先声明优先:同一深度,pom 中先写的依赖版本生效。
举例:项目直接引入 log4j 2.0;同时 A 依赖 log4j 1.0。项目到 2.0 深度是 1,到 1.0 深度是 2 → 选 2.0。
三、依赖管理五大控制手段
- dependencyManagement(依赖管理) 统一锁定依赖版本,不会自动引入依赖;子模块使用时,只写 groupId、artifactId,不用写 version。多用于父工程统一管理版本。
- scope 依赖范围 限制依赖生效的阶段,控制传递依赖是否向下传递。
| scope | 作用范围 | 是否参与打包 | 传递特性 |
|---|---|---|---|
| compile(默认) | 编译、测试、运行都有效 | ✅ | 会传递 |
| test | 仅测试编译、测试运行(JUnit) | ❌ | 不传递 |
| provided | 编译需要;运行时由容器 / JDK 提供(servlet-api) | ❌ | 不传递 |
| runtime | 编译不需要,运行时需要(JDBC 驱动) | ✅ | 会传递 |
| system | 本地系统路径 jar,不推荐 | - | 会传递 |
| import | 仅用在 dependencyManagement,导入外部 pom 的依赖版本 | - | 不传递 |
- exclusions 依赖排除 手动排除传递依赖,解决冲突。
<dependency> |
含义:引入 A,但不引入 A 自带的传递依赖 B。
- optional 可选依赖 B 依赖 C,在 B 中把 C 标记
<optional>true</optional>;当 A 依赖 B 时,C 不会传递到 A。
区别:exclusion 是使用者去排除;optional 是提供者主动标记不向下传递。
四、父工程统一依赖示例
Root 父工程 packaging=pom
<project> |
区分重点:
<dependencies>:写在父 pom,所有子模块自动继承该依赖<dependencyManagement>:只定义版本,不会自动引入依赖,子模块需要自己声明 dependencies
五、常用命令查看依赖树
# 打印完整依赖树,排查版本冲突 |
Maven 自动化部署
一、什么是 Maven 自动化部署
传统手动部署流程:代码提交 SVN/Git → 拉源码 → 构建打包 → 上传构件到私服 → 部署到服务器,多团队人工操作容易出错、版本混乱。
自动化部署整套方案组合
- 源码仓库:SVN / Git(管理源代码、打版本标签)
- Maven:项目构建
- 制品仓库:Nexus / JFrog Artifactory(存放 jar/war 等二进制构件)
maven-release-plugin:Maven 发布插件,一键完成版本升级、打标签、提交、部署到私服
二、pom 中核心配置节点
<!-- SCM:源码仓库配置,Git/SVN地址,用于release插件操作代码仓库 --> |
三、maven-release-plugin 核心目标(goal)
mvn release:clean清理 release 发布过程产生的临时文件,重置发布环境。mvn release:prepare准备发布 执行一系列动作:
- 检查本地有没有未提交代码
- 校验项目依赖不能存在 SNAPSHOT 快照
- 修改 pom:版本从
1.0-SNAPSHOT→1.0(正式版本) - 提交 pom 修改到 SCM
- 在 SVN/Git 上给代码打版本标签 tag
- 再次修改 pom:版本升级为下一个快照版本(如
1.1-SNAPSHOT),提交到 SCM - 执行项目测试,验证构建正常
mvn release:perform执行发布
- 检出刚才打好 tag 的源码
- 执行构建打包,执行 deploy,把正式版构件上传到 Nexus/JFrog 私服 Release 仓库
mvn release:rollback回滚发布 发布过程中途失败,用来撤销 release:prepare 对 pom 的修改、撤销 SCM 提交,回退到发布前状态。
完整发布顺序:
release:clean→release:prepare→release:perform发布失败:release:rollback
四、SNAPSHOT 与 Release 版本在发布中的变化
开发阶段版本:1.0-SNAPSHOT release:prepare 时:
- 临时改成
1.0(Release 正式版),打 tag,打包上传到私服 release 仓库 - 自动把 pom 版本升级为
1.1-SNAPSHOT,提交代码,供后续开发迭代
五、企业实际使用说明
maven-release-plugin适合库项目(jar 包)发布到制品仓库;- 应用部署到 Tomcat / 容器服务器,一般不会只用 Maven 直接部署到应用服务器;
- 现代企业更多结合 CI (Jenkins/GitLab CI) 流水线,代替手动敲 release 命令;
- Release 仓库不允许覆盖构件,版本一旦发布不能修改;Snapshot 仓库可以不断覆盖快照包。
Maven Web 应用
一、创建 Maven Web 项目
使用原型 maven-archetype-webapp 快速生成 Java Web 项目(war 包项目)
mvn archetype:generate \ |
二、Web 项目目录结构
trucks |
重点:packaging = war,代表打包产物是 war 包。
pom.xml 核心内容
<modelVersion>4.0.0</modelVersion> |
三、构建 Web 应用
mvn clean package |
执行流程:
- clean:清空 target 目录
- 编译资源、源码
- 执行单元测试
- war 插件打包,在
target目录生成trucks.war
四、部署 Web 应用
- 把 target 下的
trucks.war复制到 Tomcat 的webapps目录 - 重启 Tomcat
- 访问:
http://localhost:8080/trucks/index.jsp
五、常用扩展插件
- tomcat-maven-plugin:直接通过 mvn 命令启动 tomcat,不用手动复制 war 包
mvn tomcat:run |
- jetty 插件,本地快速调试 web 项目


