Maven 学习笔记(基础入门版)

本笔记聚焦 Maven 核心基础概念、常用操作和最佳实践,覆盖 Java 开发中 Maven 的全量基础使用场景,帮助零基础开发者快速上手并掌握 Maven 的核心能力。

一、Maven 核心思想与概述

1.1 什么是 Maven?

Maven 是 Apache 旗下的项目构建与依赖管理工具,是 Java 生态中最主流的项目管理标准工具。其核心设计理念有两点:

  • 约定优于配置(Convention Over Configuration):Maven 预设了标准化的项目结构、构建流程,开发者无需手动配置每一个环节,大幅减少配置工作量与学习成本。
  • 项目对象模型(Project Object Model,POM) :将项目的所有信息、配置集中在pom.xml文件中,通过该文件统一管理项目的全生命周期。

1.2 为什么需要 Maven?

  1. 解决依赖管理核心痛点:彻底解决手动导入 Jar 包的繁琐操作,以及依赖版本冲突、依赖缺失、Jar 包来源不规范等问题,实现依赖的自动化管理。
  2. 标准化项目全流程:提供统一的项目结构、标准化的构建流程(编译、测试、打包、部署),所有 Maven 项目的结构与构建逻辑一致,避免了 "本地可运行、服务器无法运行" 的环境差异问题。
  3. 提升团队协作效率:团队成员使用统一的依赖配置、构建标准,降低协作成本,同时便于项目的版本管理与持续集成落地。

二、Maven 核心概念与安装

2.1 核心概念

  • POM(Project Object Model) :Maven 的核心载体,对应项目根目录下的pom.xml文件。项目的所有配置(坐标、依赖、插件、构建规则等)都在该文件中定义,Maven 执行任务时会读取该文件完成对应操作。
  • 坐标(Coordinates) :Maven 中唯一标识一个项目 / 依赖组件 的核心标识,由三个必填字段组成,是依赖管理的基础:
    • groupId:组织标识,通常为公司 / 组织域名反写(如org.apache.commons);
    • artifactId:项目 / 组件标识,同一groupId下的唯一项目名;
    • version:版本号,标识组件的迭代版本。
  • 仓库(Repository) :Maven 存放所有 Jar 包 / 组件的统一位置,分为三类:
    • 本地仓库 :开发者本地电脑的目录,默认路径为~/.m2/repository(Windows 为C:\Users\用户名\.m2\repository)。Maven 会优先从本地仓库查找依赖,找不到再去远程仓库下载。
    • 远程仓库 / 中央仓库(Maven Central) :Maven 官方全球公共仓库,由 Sonatype 负责管理近 20 年,是全球最大的 Java 开源组件仓库,2025 年全量公共仓库的开源组件下载量达 9.8 万亿次,官方搜索地址为https://search.maven.org/
    • 私服:企业 / 团队内部搭建的私有仓库(常用工具为 Sonatype Nexus、JFrog Artifactory),用于存放内部私有组件,同时可作为中央仓库的镜像,提升依赖下载速度。
  • 依赖(Dependencies) :项目运行所需的外部 Jar 包 / 组件,在pom.xml中通过<dependencies>标签声明,Maven 会自动根据坐标下载对应依赖及其传递依赖。
  • 生命周期(Lifecycle)& 阶段(Phase) :Maven 预设的一套标准化项目构建流程,每个生命周期由一系列有序的阶段组成。执行某个阶段时,会自动按顺序执行其之前的所有前置阶段,核心阶段包括cleancompiletestpackageinstalldeploy等。
  • 插件(Plugins) :Maven 功能的实际实现者,生命周期的每个阶段都绑定了插件的具体目标(Goal),插件才是真正执行构建任务的载体,例如compile阶段绑定的是maven-compiler-plugin插件。

2.2 安装与配置

  1. 前置条件 :Maven 基于 Java 运行,需先安装 JDK(1.8 及以上版本),并配置好JAVA_HOME环境变量。
  2. 下载安装 :从 Apache Maven 官网下载对应系统的二进制压缩包(bin.zip/bin.tar.gz),解压到本地无中文、无空格的目录(如 Windows:D:\apache-maven-3.9.6,Linux/Mac:/usr/local/apache-maven-3.9.6)。
  3. 配置环境变量
    • 新建系统变量M2_HOME,值为 Maven 的解压根目录;
    • 编辑系统变量Path,新增%M2_HOME%\bin(Windows)或$M2_HOME/bin(Linux/Mac)。
  4. 验证安装 :打开命令行终端,执行mvn -v,若输出 Maven 版本、JDK 版本等信息,即为安装成功。
  5. 可选核心配置(settings.xml)settings.xml是 Maven 的全局配置文件,分为两个位置:全局配置(Maven 安装目录 /conf/settings.xml)、用户级配置(~/.m2/settings.xml,优先级更高),常用配置包括修改本地仓库路径、配置国内镜像仓库、私服地址等。

三、Maven 项目结构与 pom.xml

3.1 标准的项目目录结构(约定优于配置的核心体现)

Maven 严格约定了项目目录结构,无需额外配置即可自动识别目录用途,违背该结构会导致 Maven 无法正常识别源码,所有 Maven 项目均推荐使用该标准结构:

plaintext

复制代码
project-root  # 项目根目录
├── src
│   ├── main
│   │   ├── java        # 主Java源代码,编译后输出到target/classes
│   │   └── resources   # 主资源文件(配置文件、静态资源等),编译后复制到target/classes
│   └── test
│       ├── java        # 测试代码目录(JUnit等测试代码)
│       └── resources   # 测试专用资源文件
├── target              # 编译、打包的输出目录,自动生成,执行clean会删除
└── pom.xml             # 项目核心配置文件,必须存在

3.2 pom.xml 基础解析

pom.xml是 Maven 项目的核心,以下为最简可运行的 pom 示例 + 核心标签解析:

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">
    <!-- POM模型版本,Maven3固定为4.0.0 -->
    <modelVersion>4.0.0</modelVersion>

    <!-- 项目核心坐标,必须配置 -->
    <groupId>com.example</groupId>
    <artifactId>maven-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 打包类型,默认是jar,可选war、pom等 -->
    <packaging>jar</packaging>

    <!-- 属性定义:统一管理变量,如JDK版本、依赖版本,便于维护 -->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.13.2</junit.version>
    </properties>

    <!-- 依赖管理:声明项目需要的所有外部依赖 -->
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 构建配置:管理插件、编译输出等构建相关配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

核心标签说明:

  • 项目坐标<groupId><artifactId><version>为必填项,唯一标识当前项目,也是其他项目依赖本项目的依据。
  • 打包类型<packaging> :定义项目打包方式,默认值jar(Java 普通项目);war用于 Java Web 项目;pom用于父项目 / 聚合项目,仅做依赖和模块管理,不打包业务代码。
  • 属性定义<properties> :用于定义全局变量,格式为<变量名>值</变量名>,可通过${变量名}引用。最常用于统一管理 JDK 版本、依赖版本、编码格式,避免重复配置,便于版本统一升级。
  • 依赖管理<dependencies> :项目核心依赖配置,可包含多个<dependency>标签,每个标签对应一个依赖组件。
  • 构建配置<build> :配置项目的构建过程,核心为<plugins>插件配置,可自定义插件参数、绑定的生命周期阶段等。

四、依赖管理(核心重点)

4.1 依赖坐标与引入

  1. 依赖声明格式 :在pom.xml<dependencies>标签内,添加<dependency>标签并填入依赖的 gav 坐标即可,示例如下:

xml

复制代码
<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.14.0</version>
    </dependency>
</dependencies>
  1. 依赖搜索方式 :官方搜索地址为https://search.maven.org/,可搜索所有发布到 Maven 中央仓库的组件,步骤如下:
  • 打开站点,在搜索框输入组件名(如 commons-lang3),点击搜索;
  • 在结果中找到对应的 groupId 和 artifactId,选择需要的版本;
  • 站点会自动生成对应的<dependency>代码,直接复制粘贴到 pom.xml 的<dependencies>中即可。

4.2 依赖范围(Scope)

依赖范围用于控制依赖在编译、测试、运行三个生命周期阶段的有效性,同时影响依赖的传递性,常用 scope 如下:

表格

Scope 范围 编译有效 测试有效 运行有效 传递性 典型使用场景
compile(默认) 绝大多数业务依赖包,如 commons-lang3
provided 运行时由容器提供的包,如 Servlet API、Tomcat 相关依赖
runtime 编译时不需要、仅运行时需要的包,如 JDBC 驱动
test 仅测试阶段使用的包,如 JUnit、Mockito 测试框架
system 需通过<systemPath>指定本地 Jar 包路径,不推荐使用

4.3 依赖传递与冲突解决

  1. 传递性依赖Maven 依赖具备传递性:若 A 项目依赖 B,B 项目依赖 C,则 A 项目会自动依赖 C,无需在 A 的 pom 中手动声明 C 的依赖,Maven 会自动下载并引入所有层级的传递依赖,大幅简化依赖管理。

  2. 依赖冲突与解决原则依赖冲突的产生:当项目中多个依赖传递引入了同一个 Jar 包的不同版本,Maven 会通过以下两个固定原则决定最终使用的版本,优先级从高到低:

  • 最短路径优先:依赖的层级越浅、路径越短,优先级越高。示例:A→B→C→D (1.0),A→E→D (2.0),D (2.0) 路径长度为 2,短于 D (1.0) 的 3 级路径,最终使用 D (2.0) 版本。
  • 先声明优先:当路径长度相同时,在 pom.xml 中先声明的依赖,优先级更高。示例:A→B→D (1.0),A→E→D (2.0),两个路径长度均为 2,pom 中先声明的依赖对应的 D 版本会被使用。
  1. 冲突与传递的手动控制
  • 排除依赖<exclusions>:当传递的依赖不需要或存在版本冲突时,可手动排除指定的传递依赖,示例如下:

    xml

    复制代码
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.30</version>
        <exclusions>
            <!-- 排除指定传递依赖,仅需groupId和artifactId,无需version -->
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  • 可选依赖<optional>true</optional>:声明依赖为可选,该依赖不会传递给依赖当前项目的其他项目,示例如下:

    xml

    复制代码
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.48</version>
        <optional>true</optional>
    </dependency>

五、生命周期与常用命令

5.1 三大生命周期(相互独立)

Maven 有三套相互独立、互不影响的生命周期,每个生命周期包含多个有序的阶段(Phase),执行某个阶段时,会按顺序执行该生命周期中该阶段之前的所有前置阶段。

  1. clean 生命周期:负责清理项目,核心是删除编译打包生成的 target 目录,核心阶段为:

    • pre-clean:清理前的准备工作
    • clean:执行清理,删除 target 目录(日常最常用)
    • post-clean:清理后的收尾工作
  2. default 生命周期(核心):Maven 最核心的生命周期,负责项目的编译、测试、打包、安装、部署全流程,核心阶段按执行顺序如下:

    • validate:验证项目结构、pom 配置是否正确
    • compile:编译项目的主源代码,生成 class 文件到 target/classes
    • test:执行单元测试,不会打包和部署
    • package:将编译后的代码打包成对应格式(jar/war 等),生成到 target 目录
    • verify:验证打包结果是否有效、符合标准
    • install:将打包好的组件安装到本地 Maven 仓库,供本地其他项目依赖使用
    • deploy:将打包好的组件部署到远程仓库(私服 / 中央仓库),供团队成员使用

    关键特性:执行后面的阶段,会自动执行前面的所有阶段。例如执行mvn install,会自动按顺序执行 validate→compile→test→package→verify→install。

  3. site 生命周期:负责生成项目的站点文档、报告,日常开发中使用较少,核心阶段为 site(生成站点文档)、site-deploy(部署站点文档)。

5.2 常用命令行指令

Maven 命令格式为mvn [阶段名/插件目标] [参数],日常开发最常用的命令如下:

表格

命令 核心作用
mvn clean 清理项目,删除 target 目录
mvn compile 编译主源代码
mvn test 执行所有单元测试
mvn package 项目打包,生成 jar/war 包到 target 目录
mvn install 打包并安装到本地仓库,供本地其他项目使用
mvn deploy 打包并部署到远程仓库

常用组合命令与参数

  • mvn clean package:组合命令,先清理项目,再执行打包,避免旧编译缓存影响打包结果,日常打包最常用。
  • mvn clean install -DskipTests:清理、编译、打包、安装到本地仓库,跳过测试执行(仍编译测试代码)。
  • mvn clean install -Dmaven.test.skip=true:完全跳过测试的编译与执行,构建速度更快。

六、插件(Plugins)基础

6.1 插件与目标(Goal)

Maven 的设计核心是内核仅负责生命周期的调度,所有具体的业务功能都由插件实现

  • 插件(Plugin):Maven 功能的实现载体,每个插件都是一个 Jar 包,提供一系列相关功能。
  • 目标(Goal):插件的最小执行单元,一个插件包含多个目标,每个目标对应一个具体任务。
  • 生命周期与插件的绑定 :生命周期的每个阶段,都会绑定一个或多个插件的目标,执行生命周期阶段,本质是执行绑定的插件目标。例如compile阶段默认绑定maven-compiler-plugincompile目标。

6.2 常用内置插件

Maven 内置了多个核心插件,无需额外声明即可使用,也可手动配置参数自定义执行行为,最常用的两个插件如下:

  1. maven-compiler-plugin:Java 代码编译插件作用:负责编译 Java 源代码,配置项目的 JDK 编译版本、编码格式等,是最常用的插件,配置示例如下:

    xml

    复制代码
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <!-- 源代码使用的JDK版本 -->
                    <source>8</source>
                    <!-- 字节码兼容的JDK版本 -->
                    <target>8</target>
                    <!-- 代码编码格式 -->
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
  2. maven-surefire-plugin:测试执行插件作用:负责执行单元测试,配置测试框架、跳过测试、指定执行的测试用例等,常用配置示例如下:

    xml

    复制代码
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>3.2.5</version>
        <configuration>
            <!-- 跳过所有测试 -->
            <skipTests>true</skipTests>
        </configuration>
    </plugin>

七、多模块项目(Maven Multi-Module)基础概念

7.1 为什么需要多模块?

当项目规模扩大,单项目结构会导致代码耦合度高、难以维护、复用性差。多模块项目将大项目按功能 / 业务边界拆分为多个子模块,每个子模块独立开发、管理,核心优势如下:

  • 代码解耦,职责分离,每个模块仅负责对应功能,便于维护与迭代;
  • 模块复用,公共模块可被多个业务模块依赖,避免重复代码;
  • 便于团队协作,不同团队可负责不同模块,互不干扰。

7.2 基本结构

Maven 多模块项目采用聚合 + 继承的设计,核心分为父模块和子模块:

  1. 父模块(聚合项目)

    • 打包类型<packaging>必须为pom,不存放业务代码,仅负责管理子模块、统一管理公共依赖和插件配置。
    • 通过<modules>标签声明所有子模块,在父模块执行 mvn 命令,会自动对所有子模块执行对应命令。
    • 子模块可继承父模块的 pom 配置,统一管理依赖版本、插件配置,避免重复配置。
  2. 子模块

    • 每个子模块都是独立的 Maven 项目,有自己的 pom.xml,继承父模块的配置。
    • 子模块之间可相互依赖,实现功能调用。

标准多模块项目结构

plaintext

复制代码
parent-project  # 父项目根目录
├── module-common  # 公共工具模块
│   ├── src
│   └── pom.xml
├── module-dao     # 数据访问模块
│   ├── src
│   └── pom.xml
├── module-service # 业务服务模块
│   ├── src
│   └── pom.xml
├── module-web     # web接口模块
│   ├── src
│   └── pom.xml
└── pom.xml        # 父项目pom.xml,packaging=pom

父模块 pom 核心配置示例

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">
    <modelVersion>4.0.0</modelVersion>

    <!-- 父项目坐标 -->
    <groupId>com.example</groupId>
    <artifactId>parent-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 父项目打包类型必须是pom -->
    <packaging>pom</packaging>

    <!-- 声明所有子模块 -->
    <modules>
        <module>module-common</module>
        <module>module-dao</module>
        <module>module-service</module>
        <module>module-web</module>
    </modules>

    <!-- 统一管理属性 -->
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>5.3.30</spring.version>
        <mybatis.version>3.5.15</mybatis.version>
    </properties>

    <!-- 依赖管理:统一管理所有依赖的版本,子模块继承后无需写version -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <!-- 统一管理插件,所有子模块都会继承 -->
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.13.0</version>
                    <configuration>
                        <source>8</source>
                        <target>8</target>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

子模块 pom 核心配置示例

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">
    <parent>
        <!-- 继承父模块的坐标 -->
        <groupId>com.example</groupId>
        <artifactId>parent-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <!-- 父模块pom.xml的相对路径 -->
        <relativePath>../pom.xml</relativePath>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <!-- 子模块artifactId,groupId和version默认继承父模块,无需重复写 -->
    <artifactId>module-service</artifactId>

    <!-- 依赖声明:继承父模块的dependencyManagement,无需写version -->
    <dependencies>
        <!-- 依赖本项目的其他子模块 -->
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>module-dao</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- 继承父模块版本的公共依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
    </dependencies>
</project>

核心补充:

  • <dependencyManagement>:父模块中用于统一管理依赖版本,不会直接引入依赖,子模块继承后声明依赖时无需写 version,实现全项目依赖版本的统一。
  • <pluginManagement>:与 dependencyManagement 类似,父模块中统一管理插件的版本和配置,子模块继承后可直接使用,无需重复配置。

八、实用技巧与问题排查

8.1 配置国内镜像

Maven 默认中央仓库服务器在国外,国内下载依赖速度较慢,推荐配置阿里云 Maven 镜像,配置方式为:修改 settings.xml(推荐用户级~/.m2/settings.xml),在<mirrors>标签中添加如下配置:

xml

复制代码
<mirrors>
    <mirror>
        <id>aliyunmaven</id>
        <name>阿里云公共仓库</name>
        <url>https://maven.aliyun.com/repository/public</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

8.2 依赖冲突排查

当项目出现ClassNotFoundExceptionNoSuchMethodError等异常时,大概率是依赖版本冲突导致,可通过依赖树命令快速定位问题:

bash

运行

复制代码
# 查看项目完整依赖树,展示所有依赖及其传递依赖、版本信息
mvn dependency:tree

# 将依赖树输出到文件,便于查看
mvn dependency:tree > dependency-tree.txt

# 筛选查看指定依赖的引入情况
mvn dependency:tree -Dincludes=commons-logging

通过依赖树可清晰看到依赖的引入路径、版本、是否被排除,快速定位冲突来源,通过<exclusions>排除不需要的版本即可解决冲突。

8.3 跳过测试的几种方式

日常打包、部署时,为提升构建速度,常需要跳过单元测试,Maven 提供两种常用方式:

  1. 命令行参数方式(临时生效,推荐)

    • -DskipTests:跳过测试执行,仍编译测试代码,保证测试代码语法正确,示例:mvn clean install -DskipTests
    • -Dmaven.test.skip=true:完全跳过测试的编译与执行,构建速度更快,示例:mvn clean package -Dmaven.test.skip=true
  2. pom.xml 配置方式(永久生效) 在 pom.xml 中配置 maven-surefire-plugin,设置skipTests=true,所有构建都会跳过测试,配置示例见第六章插件配置。

相关推荐
智者知已应修善业2 小时前
【C++非递归剪枝问题凑钱方案数】2024-7-18
c语言·c++·经验分享·笔记·算法·剪枝
身如柳絮随风扬2 小时前
Git 超详细学习笔记
笔记·git
云潮汐表2 小时前
浒浦潮汐表查询2026-03-28
笔记
承渊政道2 小时前
【优选算法】(实战领略前缀和的真谛)
开发语言·数据结构·c++·笔记·学习·算法
苦瓜小生2 小时前
【Docker】| Docker学习笔记
笔记·学习·docker
Forrit2 小时前
关于Agent的几种范式
笔记
圣光SG2 小时前
Tomcat 全面学习笔记
笔记·tomcat
2501_938313402 小时前
计算机网络学习笔记】初始网络之网络发展和OSI七层模型
笔记·学习·计算机网络
deelless2 小时前
IDEA maven项目添加本地jar包
maven·intellij-idea·jar