一、Maven 介绍
1. 什么是 Maven?
Maven 是一个由 Apache 开源组织提供的项目构建与依赖管理工具。其核心功能可以概括为两点:
-
依赖管理 (Dependency Management) :对项目所依赖的第三方
jar包进行统一、规范的管理,自动解决依赖传递和版本冲突问题,实现"一键构建"。 -
项目管理 (Project Management) :提供了一套标准化的项目结构(约定优于配置)和一整套清晰的生命周期,用于完成项目的清理、编译、测试、打包、部署等构建过程。
2. Maven 的核心概念
-
仓库 (Repository)
Maven 通过三种仓库来管理
jar包,形成一个高效的供应链:-
本地仓库 (Local Repository) :位于开发者个人电脑上(默认路径:
~/.m2/repository),用于缓存从远程仓库下载的构件。 -
中央仓库 (Central Repository):由 Maven 社区维护的全球性远程仓库,包含了绝大多数开源项目的构件。访问速度可能较慢。
-
私服 (Private Repository):架设在公司内部的远程仓库,作为中央仓库的镜像和缓存。优点:速度快、安全、可部署内部构件。
-
-
坐标 (Coordinates)
坐标是 Maven 用来唯一标识一个构件(jar/war 等) 的定位地址,由三个基本元素组成,类似于数学中的三维坐标
(x, y, z)。-
groupId: 定义项目所属的组织或公司(反写的公司域名 + 项目名)。例如:org.apache,com.hgxy -
artifactId: 定义当前项目(模块)的名称。 -
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency>version: 定义当前项目的版本号。
-
二、Maven 安装与配置
1. 下载与安装
-
访问 Apache Maven 官网下载最新版。
-
将压缩包解压到一个无中文、无空格的路径 下,例如:
D:\apache-maven-3.8.6。
2. 配置阿里云镜像仓库(加速下载)
为了提升依赖下载速度,需要修改 Maven 安装目录下 conf/settings.xml文件。
-
找到
<mirrors>标签。 -
在其中添加阿里云镜像配置:
<mirror> <id>nexus-aliyun</id> <mirrorOf>central</mirrorOf> <name>Nexus aliyun</name> <url>https://maven.aliyun.com/repository/public</url> </mirror>
3. 配置本地仓库路径(可选但推荐)
默认的本地仓库路径在用户目录下的 .m2文件夹。可以自定义到一个更大的磁盘分区。
在 settings.xml中找到被注释的 <localRepository>标签,取消注释并修改:
<localRepository>D:\mvn_repository</localRepository> <!-- 自定义的本地仓库路径 -->
4. 配置环境变量(可选,方便命令行使用)
-
新建系统变量
MAVEN_HOME,值为 Maven 的安装路径,如:D:\apache-maven-3.8.6 -
在
Path变量中追加:%MAVEN_HOME%\bin -
验证:打开命令行,输入
mvn -v,看到版本信息即表示成功。
三、IDEA 集成 Maven
1. 全局配置(推荐)
在 IDEA 中一次配置,所有新建项目都会生效。
-
路径 :
File->Settings->Build, Execution, Deployment->Build Tools->Maven -
关键配置:
-
Maven home path: 指向你的 Maven 安装目录。 -
User settings file: 指向你修改过的settings.xml文件(确保已配置阿里云镜像)。 -
Local repository: 此处会自动读取上一步配置的本地仓库路径。
-
2. Maven 项目标准目录结构
创建 Maven 项目后,会自动生成以下约定俗成的目录结构:
your-project
├── src
│ ├── main
│ │ ├── java # 存放项目的 Java 源代码
│ │ └── resources # 存放项目的主配置文件(如:mybatis-config.xml, spring.xml)
│ └── test
│ ├── java # 存放项目的测试代码(如:Junit 测试)
│ └── resources # 存放测试相关的配置文件
├── target # 项目构建输出目录(编译后的 class 文件,打包的 jar/war 等)
└── pom.xml # Maven 项目的核心配置文件
3. 添加与下载依赖
在项目的 pom.xml文件的 <dependencies>标签内,添加所需的依赖坐标。IDEA 会自动从远程仓库下载依赖到本地仓库。
4. 解决依赖下载失败问题
下载过程中若网络中断,会生成以 .lastUpdated结尾的文件,导致后续无法继续下载。
-
解决方案:
-
删除本地仓库中对应依赖文件夹下的所有
.lastUpdated文件。 -
或者在 IDEA 中执行
Maven面板的Reload project按钮,强制重新下载。
-
四、Maven 生命周期
Maven 的生命周期 (Lifecycle) 由一系列有序的阶段 (Phase) 组成,执行后面的阶段会自动执行前面所有的阶段。
-
清理周期 (clean) :
mvn clean- 删除
target目录,清理上次构建的结果。
- 删除
-
默认周期/构建周期 (default):最核心的生命周期。
-
compile: 编译主程序的源码。 -
test: 使用单元测试框架(如 JUnit)运行测试。 -
package: 将编译后的代码打包成指定格式(jar/war)。 -
install: 将打好的包安装到本地仓库,供其他本地项目依赖。 -
deploy: 将最终的包复制到远程仓库(私服),供其他开发者或项目共享。
-
-
站点周期 (site) :
mvn site- 生成项目的站点文档。
五、依赖冲突与解决方案
当项目引入的多个依赖,间接引入了同一个 jar包的不同版本时,就会产生依赖冲突。Maven 有内置的调解原则,但我们也需掌握手动解决方案。
Maven 内置调解原则:
-
路径近者优先原则:依赖传递路径短的版本优先。直接依赖 > 间接依赖。
-
第一声明者优先原则 :在
pom.xml中,同层级的依赖声明,谁声明在前,谁的版本就被采用。
手动解决方案:
-
排除依赖 (Exclusion)
不想要某个依赖传递进来的特定版本,可以将其排除。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.8.RELEASE</version> <exclusions> <exclusion> <!-- 排除 spring-context 所依赖的 spring-core 5.1.8 --> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> </exclusions> </dependency> -
版本锁定 (Dependency Management)
在父工程或当前工程的
<dependencyManagement>标签中,统一声明依赖的版本。这是最推荐、最常用的方式。<properties> <!-- 定义版本号属性,便于统一管理 --> <spring.version>5.2.0.RELEASE</spring.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> <!-- 引用上面定义的属性 --> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </dependencyManagement> <!-- 在 dependencies 中引用时,无需再写版本号 --> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <!-- 版本被锁定为 5.2.0 --> </dependency> </dependencies>
六、依赖作用域 (Scope)
<scope>标签用于控制依赖在编译、测试、运行、打包等不同阶段的有效性。
| Scope | 对主代码(classpath)有效 | 对测试代码有效 | 会打包发布 | 典型示例 |
|---|---|---|---|---|
| compile | ✅ | ✅ | ✅ | Spring-Core |
| test | ❌ | ✅ | ❌ | JUnit |
| runtime | ❌ | ✅ | ✅ | MySQL 驱动 |
| provided | ✅ | ✅ | ❌ | Servlet-API, Tomcat |
七、聚合与继承(多模块项目)
在大型项目中,通常会将一个项目拆分为多个模块(如:dao, service, web)进行开发。Maven 的聚合与继承特性完美支持此模式。
1. 概念与关系
-
聚合 (Aggregation) :一个父模块 (通常打包方式为
pom)通过<modules>将多个子模块组织在一起。对父模块执行 Maven 命令,会传递到所有子模块。 -
继承 (Inheritance) :子模块通过
<parent>标签继承父模块的pom.xml配置,从而统一管理依赖版本、插件等。
2. 标准项目结构
maven-parent (父工程,pom)
├── maven-dao (子模块,jar)
├── maven-service (子模块,jar,依赖 maven-dao)
└── maven-web (子模块,war,依赖 maven-service)
3. 关键配置示例
-
父工程 (maven-parent) 的 pom.xml
<groupId>com.hg</groupId> <artifactId>maven-parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <!-- 打包方式必须为 pom --> <!-- 聚合:声明所有子模块 --> <modules> <module>maven-dao</module> <module>maven-service</module> <module>maven-web</module> </modules> <!-- 继承:在 dependencyManagement 中统一管理依赖版本 --> <dependencyManagement> <dependencies> <!-- 这里声明所有公共依赖及其版本 --> </dependencies> </dependencyManagement> -
子模块 (maven-service) 的 pom.xml
<!-- 继承父工程 --> <parent> <groupId>com.hg</groupId> <artifactId>maven-parent</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>maven-service</artifactId> <packaging>jar</packaging> <dependencies> <!-- 依赖另一个子模块 maven-dao --> <dependency> <groupId>com.hg</groupId> <artifactId>maven-dao</artifactId> <version>${project.version}</version> <!-- 版本与父工程一致 --> </dependency> <!-- 其他依赖无需再写版本号(如果在父工程dependencyManagement中已声明)--> </dependencies>