1. Maven 的概念
1.1 什么是 Maven
- 定义 :Maven 译为 "专家""内行",是跨平台的项目管理工具,主要服务于 Java 平台的项目构建、依赖管理、项目信息管理。
- 理想的项目构建特点:高度自动化、跨平台、可重用组件、标准化。
- 依赖与依赖管理 :
- 依赖:项目运行所需的第三方库(如 A1.0 依赖 B2.0,B2.0 依赖 C3.0)。
- 依赖管理目的:自动下载依赖、统一管理依赖版本,避免手动拷贝 jar 包的繁琐。
- 项目信息类型:项目名称 / 描述、开发人员信息、开发者信息等。
1.2 依赖管理
- 核心作用:管理第三方依赖包(自动从仓库下载)和自定义模块(像引用第三方包一样引用自身项目模块)。
- 传统项目依赖管理:从官网下载 jar 包 → 手动拷贝到项目 lib 目录。
- Maven 依赖管理 :编写
pom.xml配置文件 → 引入依赖坐标 → Maven 自动从中央仓库 / 远程仓库下载 jar 包到本地仓库。
1.3 项目构建
- 定义 :从编写源代码到编译、测试、运行、打包、部署的完整流程。
- 传统项目构建流程:打开 IDEA 编写代码 / 配置文件 → 手动编译 → JUnit 单元测试 → 手动打 war 包 → 部署到 Tomcat 运行。
- Maven 项目构建流程 :Maven 标准化构建阶段,每个阶段通过命令执行,流程为:清理 → 编译 → 测试 → 报告 → 打包 → 部署。
- Maven 构建优势 :
- 命令行完成全流程(如
mvn tomcat:run直接发布运行项目)。 - 标准化构建阶段,利于大型团队协作。
- 命令行完成全流程(如
1.4 应用场景
- 开发流程:
- 开发人员按 Maven 标准目录结构编写代码,提交到 Git 版本控制服务器。
- 测试服务器拉取 Git 中的 Java 源码,通过 Maven 自动执行清理、编译、测试、打包、部署。
- 依赖环境:JDK、Web 服务器(如 Tomcat)、Maven、Git、测试主机。
1.5 为什么使用 Maven(对比其他工具)
| 工具 | 不足 |
|---|---|
| IDE(Eclipse/IDEA) | 手工操作多(编译、测试、部署独立),IDE 配置不同易导致本地代码换环境编译出错。 |
| Ant | 无约定目录结构,需明确定义 "做什么、何时做",无生命周期,无集成依赖管理。 |
- Maven 优势 :
- 有约定目录结构(知道代码存放 / 输出路径)。
- 有完整生命周期(如
mvn install自动执行编译→测试→打包)。 - 仅需配置
pom.xml,源码放默认目录,Maven 自动处理后续操作。 - 内置依赖管理和仓库管理。
1.6 Maven 模型
Maven 核心由 4 大模型组成,相互协作完成项目管理:
- 项目对象模型(POM) :核心是
pom.xml,定义项目基本信息、依赖、构建配置。 - 依赖管理模型(Dependency):管理项目依赖的第三方包或自定义模块,通过坐标定位依赖。
- 构建生命周期与阶段(Build Lifecycle & Phases):标准化构建流程(如 clean、default、site 生命周期)。
- 插件(Plug-in) :实际执行构建任务(如
maven-compiler-plugin负责编译),绑定到生命周期阶段。 - 仓库(Repository) :存储依赖构件(本地仓库
~/.m2/repository、中央仓库、远程仓库)。
2. 初识 Maven
2.1 Maven 安装
2.1.1 安装准备
- JDK 要求:安装 JDK 1.8 及以上版本。
- Maven 下载 :
- 官方地址:http://maven.apache.org/download.html
- 历史版本(3.6.0):https://archive.apache.org/dist/maven/maven-3/3.6.0/binaries/
- 安装方式:解压到无中文路径 的目录(如
C:\software\maven\apache-maven-3.6.0)。
2.1.2 安装目录分析
| 目录 / 文件 | 作用 |
|---|---|
| bin | 包含 Maven 运行脚本(如mvn.cmd)。 |
| boot | 包含plexus-classworlds类加载器框架(Maven 运行的基础)。 |
| conf | 包含核心配置文件settings.xml(全局配置)。 |
| lib | 包含 Maven 运行所需的 Java 类库。 |
| LICENSE/NOTICE | Maven 版本信息、第三方软件声明。 |
2.1.3 环境变量配置
-
配置 MAVEN_HOME:
- 变量名:
MAVEN_HOME - 变量值:Maven 解压路径(如
C:\software\maven\apache-maven-3.6.0) - 作用:升级时仅需修改此路径,无需修改其他配置。
- 变量名:
-
配置 MAVEN_OPTS(解决大型项目内存溢出):
- 变量名:
MAVEN_OPTS - 变量值:
-Xms128m -Xmx512m(初始内存 128M,最大内存 512M)。
- 变量名:
-
配置 Path:
- 在系统变量
Path末尾添加:%MAVEN_HOME%\bin - 作用:使命令行可直接识别
mvn命令。
- 在系统变量
2.1.4 验证配置
- 打开 cmd 命令行,输入
mvn -v,若显示 Maven 版本、JDK 版本信息,则配置成功。
2.2 第一个 Maven 项目(Hello 项目)
2.2.1 约定目录结构
Hello(项目根目录)
├─src
│ ├─main
│ │ ├─java # 存放项目.java源码
│ │ └─resources # 存放项目资源文件(如spring、mybatis配置)
│ └─test
│ ├─java # 存放测试.java文件(如JUnit测试类)
│ └─resources # 存放测试资源文件
├─target # 项目输出目录(编译后的class、打包文件)
└─pom.xml # Maven核心配置文件
2.2.2 配置 pom.xml
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>
<!-- 项目坐标:groupId(组织标识)、artifactId(项目名)、version(版本) -->
<groupId>cn.tx.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version> <!-- SNAPSHOT表示快照版本 -->
<name>Hello</name>
<!-- 依赖配置 -->
<dependencies>
<!-- JUnit测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope> <!-- 仅测试阶段生效 -->
</dependency>
</dependencies>
</project>
2.2.3 创建源码文件(Hello.java)
- 路径:
src/main/java/cn/tx/maven/Hello.java
java
package cn.tx.maven;
public class Hello {
public String sayHello(String name) {
return "Hello " + name + "!";
}
}
2.2.4 创建测试文件(HelloTest.java)
- 路径:
src/test/java/cn/tx/maven/HelloTest.java
java
package cn.tx.maven;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
public class HelloTest {
@Test
public void testHello() {
Hello hello = new Hello();
String result = hello.sayHello("maven");
assertEquals("Hello maven!", result); // 断言测试结果
}
}
2.2.5 执行 Maven 命令(项目根目录下)
| 命令 | 作用与效果 |
|---|---|
mvn compile |
编译主代码,生成target/classes目录(存放.class 文件)。 |
mvn clean |
清理项目,删除target目录。 |
mvn clean compile |
先清理再编译,确保编译结果是最新的。 |
mvn clean test |
先清理,再编译,最后执行测试(生成target/test-classes,输出测试报告)。 |
mvn clean package |
先清理→编译→测试,最后打包(生成target/Hello-0.0.1-SNAPSHOT.jar)。 |
mvn clean install |
先清理→编译→测试→打包,最后将 jar 包安装到本地仓库(供其他项目依赖)。 |
2.3 第二个 Maven 项目(HelloFriend,依赖 Hello 项目)
2.3.1 约定目录结构
同 Hello 项目,根目录命名为HelloFriend。
2.3.2 配置 pom.xml(添加 Hello 项目依赖)
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>
<groupId>cn.tx.maven</groupId>
<artifactId>HelloFriend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>HelloFriend</name>
<dependencies>
<!-- JUnit测试依赖 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- 依赖Hello项目(需先执行Hello项目的mvn install) -->
<dependency>
<groupId>cn.tx.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope> <!-- 编译/测试/运行阶段均生效 -->
</dependency>
</dependencies>
</project>
2.3.3 源码与测试文件
- HelloFriend.java (路径:
src/main/java/cn/tx/maven/):调用 Hello 类的sayHello方法。 - HelloFriendTest.java (路径:
src/test/java/cn/tx/maven/):测试 HelloFriend 的功能。
2.3.4 打包报错与解决
- 报错信息 :
Could not find artifact cn.tx.maven:Hello:jar:0.0.1-SNAPSHOT(找不到 Hello 依赖)。 - 解决方法 :进入 Hello 项目根目录,执行
mvn clean install,将 Hello 的 jar 包安装到本地仓库,再重新执行 HelloFriend 的mvn package。
2.4 Maven 仓库配置
2.4.1 仓库概念与分类
- 仓库定义:统一存储 Maven 共享构件(jar、war、pom 等)的位置。
- 仓库布局 :按坐标路径存储,格式为
groupId/artifactId/version/artifactId-version.packaging(如cn/tx/maven/Hello/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar)。 - 仓库分类 :
- 本地仓库 :默认路径
~/.m2/repository(Windows:C:\Users\用户名\.m2\repository),可修改;每个用户仅 1 个本地仓库,优先从本地仓库获取依赖。 - 远程仓库 :
- 中央仓库:Maven 默认远程仓库(http://repo1.maven.org/maven2),包含大量开源 Java 构件,需联网访问。
- 私服:架设在局域网内的远程仓库,代理中央仓库,存储公司内部构件。
- 本地仓库 :默认路径
2.4.2 本地仓库配置(修改 settings.xml)
-
配置方式分两种 :
- 全局配置 (影响所有用户):修改
%MAVEN_HOME%\conf\settings.xml,找到<localRepository>标签,替换为自定义路径(如D:\ProgramFiles\shoprepository)。 - 用户级配置 (仅影响当前用户):在
~/.m2/目录下创建settings.xml,配置同上。
- 全局配置 (影响所有用户):修改
-
示例配置 :
XML<localRepository>D:\ProgramFiles\shoprepository</localRepository>
2.5 IDEA 整合 Maven
2.5.1 IDEA 全局 Maven 配置(所有项目生效)
- 启动 IDEA,进入
Configure → Settings → Build, Execution, Deployment → Build Tools → Maven。 - 配置 3 个核心参数:
- Maven home directory :选择 Maven 解压路径(如
D:\TOOLS\maven\apache-maven-3.5.4)。 - User settings file :选择
%MAVEN_HOME%\conf\settings.xml(或用户级settings.xml)。 - Local repository :自动加载
settings.xml中配置的本地仓库路径。
- Maven home directory :选择 Maven 解压路径(如
- 点击
Apply → OK,配置生效。
2.5.2 IDEA 创建 Maven Java 项目
- 新建项目:
New Project → Maven → 不勾选模板(或选quickstart)→ 填写GroupId/ArtifactId/Version → 选择Maven配置 → 完成。 - 测试依赖引入:在
pom.xml中添加 JUnit 依赖,IDEA 自动下载并识别。
2.5.3 IDEA 创建 Maven Java Web 项目
- 新建项目:
New Project → Maven → 勾选"Create from archetype" → 选择maven-archetype-webapp` → 填写坐标 → 选择 Maven 配置 → 完成。 - 解决项目初始化慢 :进入
Settings → Build, Execution, Deployment → Build Tools → Maven → Runner,在VM Options中添加-DarchetypeCatalog=local(从本地加载模板)。 - 项目配置 :
- 检查 Web 项目结构(
File → Project Structure → Modules),确保src/main/java等目录存在且标记正确。 - 检查
web.xml路径(默认src/main/webapp/WEB-INF/web.xml)。 - 配置 Tomcat:
Run → Edit Configurations → 添加Tomcat Server → 部署Web项目(选择war包)→ 启动测试。
- 检查 Web 项目结构(
2.5.4 IDEA 导入既有 Maven 项目
- 操作步骤:
File → Open → 选择项目根目录的pom.xml → 选择"Open as Project" → 完成。 - 依赖识别:若项目依赖其他自定义模块(如 HelloFriend 依赖 Hello),IDEA 会自动识别本地仓库中的依赖 jar 包。
2.6 Maven 项目视图
- 作用:查看项目属性(坐标、依赖、插件),执行 Maven 操作(清理、编译、测试、打包)。
- 打开方式 :IDEA 右侧边栏
Maven → 选择项目。 - 核心功能 :
- 查看
pom.xml配置。 - 执行 Maven 命令(如
clean、compile、package)。 - 查看依赖树(识别依赖冲突)。
- 管理 Maven 插件。
- 查看
3. Maven 进阶(3.1-3.5)
3.1 pom.xml 文件
- 核心地位 :类比 Make 的
MakeFile、Ant 的build.xml,是 Maven 项目的 "心脏"。 - 作用 :
- 定义项目基本信息(坐标、名称、描述)。
- 声明项目依赖(
dependencies标签)。 - 配置项目构建(如源码目录、插件、打包方式)。
- 本质:通过项目对象模型(POM)描述项目,Maven 基于此文件执行所有操作。
3.2 坐标
3.2.1 坐标概念
- 定义:Maven 中构件的唯一标识,用于定位依赖(第三方包或自定义模块)。
- 必选元素 :
groupId、artifactId、version(3 个元素组合唯一确定一个构件)。 - 可选元素 :
packaging:打包方式,默认jar(Java 项目),可选war(Web 项目)、pom(父项目)。classifier:用于区分同一坐标下的不同附属构件(如源码包-sources.jar)。
3.2.2 坐标意义
- 为 Maven 世界的海量构件提供统一标识规范。
- 让机器可自动根据坐标查找、下载依赖(无需人工干预)。
3.2.3 坐标元素含义
| 元素 | 含义与示例 |
|---|---|
groupId |
组织标识,通常为 "公司网址反写 + 项目名"(如cn.tx.maven,com.alibaba.fastjson)。 |
artifactId |
项目 / 模块名,通常为 "项目名 - 模块名"(如Hello,HelloFriend)。 |
version |
版本号,格式:大版本.分支版本.小版本-限定符,如0.0.1-SNAPSHOT(快照版)、1.0-RELEASE(稳定版)。 |
packaging |
打包类型,默认jar,Web 项目用war,父项目用pom。 |
3.2.4 坐标示例
-
自定义项目坐标 (HelloFriend):
XML<groupId>cn.tx.maven</groupId> <artifactId>HelloFriend</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> -
第三方依赖坐标 (JUnit):
XML<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> </dependency>
3.2.5 第三方依赖查找方法
- 访问 Maven 中央仓库搜索地址:https://mvnrepository.com/。
- 搜索依赖名称(如
mybatis、fastjson)。 - 选择对应版本,复制坐标到
pom.xml的dependencies标签中。
3.3 依赖
3.3.1 依赖的意义
- 解决项目对第三方库的依赖问题:
- 自动下载依赖(包括递归依赖,如 A 依赖 B,B 依赖 C,Maven 自动下载 A、B、C)。
- 统一管理依赖版本(避免版本冲突)。
- 减少手动拷贝 jar 包的繁琐,降低项目维护成本。
3.3.2 依赖的使用
-
核心标签 :
<dependencies>:依赖集合,包含多个<dependency>。<dependency>:单个依赖,核心配置为三维坐标 (groupId、artifactId、version)和scope(依赖范围)。
-
示例 (依赖 Hello 项目和 JUnit):
XML<dependencies> <!-- 自定义模块依赖 --> <dependency> <groupId>cn.tx.maven</groupId> <artifactId>Hello</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> </dependency> <!-- 第三方依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> </dependencies>
3.4 依赖范围
3.4.1 核心概念
- 背景:Maven 项目有三套 classpath(编译、测试、运行),依赖范围控制依赖在哪些 classpath 中生效。
- 6 种依赖范围 :
compile(默认)、test、provided、runtime、system、import(常用前 4 种)。
3.4.2 依赖范围对比表
| 依赖范围(Scope) | 主代码 classpath 有效 | 测试代码 classpath 有效 | 运行时 classpath 有效(打包包含) | 示例 |
|---|---|---|---|---|
compile |
Y | Y | Y | log4j、Hello 模块 |
test |
N | Y | N | JUnit |
provided |
Y | Y | N | servlet-api(由 Web 容器提供) |
runtime |
N | Y | Y | JDBC 驱动(编译用接口,运行用实现) |
3.5 依赖传递和可选依赖
3.5.1 依赖传递
- 定义:间接依赖自动继承(如 A 依赖 B,B 依赖 C,则 A 间接依赖 C)。
- 应用场景 :
- 第一直接依赖:HelloFriend 依赖 Hello(A→B)。
- 第二直接依赖:MakeFriend 依赖 HelloFriend(A→B→C)。
- 结果:MakeFriend 无需显式配置,自动依赖 Hello。
3.5.2 依赖范围对传递依赖的影响
| 第一直接依赖范围 | 第二传递依赖范围 | 最终传递依赖范围 |
|---|---|---|
compile |
compile |
compile |
compile |
runtime |
runtime |
test |
任意 | 无(不传递) |
provided |
任意 | provided |
runtime |
compile |
runtime |
runtime |
runtime |
runtime |
3.5.3 依赖阻断(可选依赖)
-
作用:阻止依赖传递(如 HelloFriend 依赖 Hello,但不希望 MakeFriend 依赖 Hello)。
-
配置方式 :在依赖中添加
<optional>true</optional>。 -
示例 (HelloFriend 的 pom.xml):
XML<dependency> <groupId>cn.tx.maven</groupId> <artifactId>Hello</artifactId> <version>0.0.1-SNAPSHOT</version> <scope>compile</scope> <optional>true</optional> <!-- 阻断Hello的传递依赖 --> </dependency>
3.5.4 排除特定依赖(exclusion)
- 作用:显式排除依赖中的某个子依赖(解决依赖冲突)。
- 配置方式 :在
<dependency>中添加<exclusions>和<exclusion>(无需指定版本)。
XML
<dependency>
<groupId>cn.tx.maven</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>xxx.xxx</groupId> <!-- 要排除的依赖groupId -->
<artifactId>xxx</artifactId> <!-- 要排除的依赖artifactId -->
</exclusion>
</exclusions>
</dependency>