Maven 详解:核心概念、配置文件、生命周期与依赖管理
Maven 是一款基于项目对象模型(POM)的软件项目管理和构建自动化工具,主要用于 Java 项目。其核心目标是简化构建过程,提供统一的构建系统、项目信息和依赖管理。
- 核心概念
| 概念 | 说明 | 作用/示例 |
|---|---|---|
| POM (Project Object Model) | Maven 项目的核心配置文件,名为 pom.xml。它定义了项目的基本信息、依赖、插件、构建配置等。 |
项目的"蓝图",所有构建行为都基于此文件。 |
| 坐标 (Coordinates) | 用于唯一标识一个项目或构件(artifact)。由 groupId, artifactId, version 三个基本元素组成(packaging 和 classifier 可选)。 |
com.company.project:my-app:1.0.0。Maven 通过坐标在仓库中定位和引用构件。 |
| 仓库 (Repository) | 存储项目依赖和插件的地方。分为本地仓库 (用户计算机上的缓存)和远程仓库(如中央仓库 Maven Central、公司私服 Nexus/Artifactory)。 | 依赖查找顺序:本地仓库 -> 远程仓库。远程仓库地址在 pom.xml 或 settings.xml 中配置。 |
| 依赖 (Dependency) | 项目运行或编译所需的外部库(JAR 包)。在 pom.xml 的 <dependencies> 节点中声明。 |
Maven 会自动从仓库下载声明的依赖及其传递性依赖。 |
| 生命周期 (Lifecycle) | 一套预设的、有序的构建阶段(phase)。Maven 有三个内置的生命周期:clean, default(构建), site(生成站点)。 |
执行一个阶段(如 package)会自动执行该阶段之前的所有阶段(如 validate, compile, test)。 |
| 插件与目标 (Plugin & Goal) | Maven 的所有功能都由插件实现。一个插件包含多个目标(goal),每个目标是具体的任务(如 maven-compiler-plugin:compile)。 |
生命周期阶段通常绑定了一个或多个插件目标。用户也可以直接运行插件目标(如 mvn dependency:tree)。 |
- 配置文件详解
2.1 POM 文件 (pom.xml)
这是项目的核心配置文件,位于项目根目录。
xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 模型版本,固定为 4.0.0 -->
<modelVersion>4.0.0</modelVersion>
<!-- 项目坐标 -->
<groupId>com.example</groupId> <!-- 组织或公司的唯一标识 -->
<artifactId>my-project</artifactId> <!-- 项目名称 -->
<version>1.0-SNAPSHOT</version> <!-- 项目版本,SNAPSHOT表示开发版 -->
<packaging>jar</packaging> <!-- 打包方式,如 jar, war, pom -->
<!-- 项目属性定义,常用于统一版本号 -->
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring.version>5.3.23</spring.version>
</properties>
<!-- 依赖管理 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version> <!-- 引用上面定义的属性 -->
<scope>compile</scope> <!-- 依赖作用范围 -->
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope> <!-- 仅在测试时有效 -->
</dependency>
</dependencies>
<!-- 构建配置,包括插件管理 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2 用户级/全局级设置文件 (settings.xml)
位于 MAVEN_HOME/conf/(全局)或 ~/.m2/(用户)。用于配置 Maven 运行环境,如本地仓库路径、镜像仓库、代理服务器、认证信息等。
xml
<settings>
<!-- 设置本地仓库路径,默认为 ~/.m2/repository -->
<localRepository>D:\maven-repo</localRepository>
<mirrors>
<!-- 配置镜像仓库,用于加速下载或替换中央仓库 -->
<mirror>
<id>aliyun-maven</id>
<mirrorOf>central</mirrorOf>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
</mirrors>
<profiles>
<!-- 可以定义不同的环境配置,通过id激活 -->
<profile>
<id>jdk-11</id>
<activation>
<jdk>11</jdk>
</activation>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</profile>
</profiles>
</settings>
- 构建生命周期与常用命令
Maven 的构建过程基于生命周期,每个生命周期包含一系列按顺序执行的阶段(phase)。
clean 生命周期:清理项目。
pre-clean->clean(删除target目录)->post-clean
default 生命周期:核心的构建和部署流程。
validate(验证项目正确性)compile(编译主代码)test-compile(编译测试代码)test(运行单元测试)package(打包,如生成 JAR 或 WAR 文件)verify(集成测试)install(将包安装到本地仓库)deploy(将包部署到远程仓库)
site 生命周期:生成项目文档和报告。
常用 Maven 命令示例:
bash
# 清理项目并打包
mvn clean package
# 编译并运行所有测试
mvn test
# 将项目安装到本地仓库,供其他项目依赖
mvn install
# 跳过单元测试进行打包
mvn package -DskipTests
# 显示项目依赖树,用于分析依赖冲突
mvn dependency:tree
# 运行一个特定的插件目标
mvn help:effective-pom # 查看有效的POM(合并了所有父POM和settings)
- 依赖管理详解
依赖管理是 Maven 的核心功能之一,其强大之处在于自动处理依赖的传递和冲突。
4.1 依赖范围 (<scope>)
指定依赖在哪些 classpath 中有效。
| 范围 | 说明 | 示例场景 |
|---|---|---|
compile |
默认值。编译、测试、运行都有效。 | Spring Core, Apache Commons |
provided |
编译和测试有效,运行时由容器或JDK提供。 | Servlet API, JSP API |
runtime |
测试和运行有效,编译时不需要。 | JDBC 驱动(如 MySQL Connector) |
test |
仅在测试编译和运行阶段有效。 | JUnit, Mockito |
system |
类似 provided,但需通过 <systemPath> 显式指定本地路径。 |
不推荐使用,不利于移植。 |
4.2 依赖传递与排除
当项目 A 依赖 B,B 依赖 C,则 A 会自动传递依赖 C。这可能导致依赖冲突 (不同路径引入了同一依赖的不同版本)。Maven 采用**"最短路径优先"和"先声明优先"**原则解决冲突。
可以使用 <exclusion> 主动排除不想要的传递性依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId> <!-- 排除默认日志 -->
</exclusion>
</exclusions>
</dependency>
4.3 依赖管理 (<dependencyManagement>)
通常用在父 POM 或多模块项目中,用于统一管理子模块的依赖版本。它只声明版本,子模块需要显式引入依赖才会生效,这确保了版本的一致性。
xml
<!-- 父POM中 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.23</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 子模块中,无需指定版本 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</dependency>
</dependencies>
- 标准目录结构
Maven 遵循约定优于配置的原则,有标准的项目目录结构:
my-project/
├── pom.xml # 项目对象模型文件
├── src/
│ ├── main/ # 主代码和资源
│ │ ├── java/ # Java源代码
│ │ ├── resources/ # 资源文件(配置文件等)
│ │ └── webapp/ # Web应用资源(WEB-INF/, 用于war项目)
│ └── test/ # 测试代码和资源
│ ├── java/ # 测试Java源代码
│ └── resources/ # 测试资源文件
└── target/ # 构建输出目录(编译后的类、jar包等)
这种标准化结构使得项目易于理解和构建,无需额外配置。