第一章:入门篇 — Maven 核心概念与基础使用

目标:理解 Maven 解决什么问题,掌握 POM、坐标、仓库和基础命令,能够从零创建并构建一个标准 Java 项目。


目录

  1. [Maven 是什么](#Maven 是什么)
  2. 安装与配置
  3. [POM 文件解析](#POM 文件解析)
  4. 坐标系统与版本语义
  5. 仓库管理
  6. 基础命令全流程
  7. [实战 Demo:maven-hello-world](#实战 Demo:maven-hello-world)
  8. 常见问题与避坑
  9. 专家面试题

1. Maven 是什么

Maven 是 Java 生态中最常用的项目构建与依赖管理工具。它把一个 Java 项目的构建信息集中写在 pom.xml 中,由 Maven 根据固定生命周期完成编译、测试、打包、安装、发布等工作。

Maven 核心价值

能力 解决的问题 典型场景
项目对象模型 POM 项目信息、依赖、插件、构建规则集中管理 多人协作时保持构建一致
约定优于配置 默认目录、默认生命周期、默认插件绑定 新项目无需手写大量脚本
依赖管理 自动下载依赖、处理传递依赖 引入 Spring Boot、JUnit、数据库驱动
生命周期 把构建流程拆成标准阶段 compiletestpackageinstall
插件扩展 所有构建能力都由插件实现 编译、测试、打包、代码检查、发布

Maven 与 Ant、Gradle 对比

维度 Ant Maven Gradle
核心定位 构建脚本工具 标准化构建与依赖管理 可编程构建平台
配置方式 XML 任务脚本 XML POM 模型 Groovy/Kotlin DSL
默认约定 少,需要手写 强,约定优于配置 强,可灵活扩展
依赖管理 原生较弱 成熟稳定 成熟且支持变体
学习重点 任务编排 生命周期、POM、插件 Task、Plugin、DSL、缓存

Maven 的优势是稳定、标准、生态广。企业 Java 后端项目、Spring Boot 项目、开源组件发布仍大量使用 Maven。


2. 安装与配置

环境要求

bash 复制代码
java -version
mvn -version

建议:

工具 推荐版本 说明
JDK 17+ Spring Boot 3.x 和现代企业项目推荐 Java 17
Maven 3.9+ 依赖解析、安全和性能更好
IDE IntelliJ IDEA 对 Maven 项目导入、依赖树、Profile 支持完整

Maven 目录结构

text 复制代码
apache-maven-3.9.x/
├── bin/                 # mvn、mvnDebug 命令
├── boot/                # Maven 自启动依赖
├── conf/settings.xml    # 全局配置
└── lib/                 # Maven 运行依赖

settings.xml 关键配置

settings.xml 不是项目配置,而是"用户或机器级配置"。常见位置:

text 复制代码
全局配置:${MAVEN_HOME}/conf/settings.xml
用户配置:~/.m2/settings.xml

常用配置示例:

xml 复制代码
<settings>
  <localRepository>/Users/yourname/.m2/repository</localRepository>

  <mirrors>
    <mirror>
      <id>aliyunmaven</id>
      <mirrorOf>central</mirrorOf>
      <name>Aliyun Maven Central Mirror</name>
      <url>https://maven.aliyun.com/repository/central</url>
    </mirror>
  </mirrors>

  <servers>
    <server>
      <id>company-releases</id>
      <username>${env.MAVEN_REPO_USER}</username>
      <password>${env.MAVEN_REPO_PASSWORD}</password>
    </server>
  </servers>

  <profiles>
    <profile>
      <id>company</id>
      <repositories>
        <repository>
          <id>company-public</id>
          <url>https://repo.example.com/repository/maven-public/</url>
        </repository>
      </repositories>
    </profile>
  </profiles>
</settings>

重要原则:

配置 放在哪里 原因
依赖版本、插件版本 项目 pom.xml 项目成员必须一致
私服账号密码 settings.xml 或 CI Secret 避免提交敏感信息
本地仓库路径 settings.xml 属于个人机器配置
Profile 环境变量 POM 或 settings 项目环境放 POM,个人环境放 settings

3. POM 文件解析

POM 是 Project Object Model 的缩写,描述一个项目的身份、依赖、构建规则和发布方式。

最小 POM:

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.example</groupId>
  <artifactId>maven-hello-world</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>
</project>

GAV 坐标

字段 含义 示例
groupId 组织或公司域名反写 com.example.maven.demo
artifactId 模块或产物名称 maven-demo-core
version 版本号 1.0.0-SNAPSHOT

一个依赖的完整身份由 groupId:artifactId:version 决定。

packaging 类型

类型 产物 常见用途
jar .jar Java 库、Spring Boot 应用
war .war 传统 Servlet 容器部署
pom 无代码产物 父工程、BOM、聚合工程
maven-plugin Maven 插件 JAR 自定义插件

本项目中:

text 复制代码
maven-demo                  packaging=pom
maven-demo-bom              packaging=pom
maven-demo-api              packaging=jar
maven-demo-core             packaging=jar
maven-demo-plugin           packaging=maven-plugin
maven-demo-web              packaging=jar

properties

properties 用来集中定义版本和构建参数:

xml 复制代码
<properties>
  <java.version>17</java.version>
  <spring-boot.version>3.2.5</spring-boot.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

最佳实践:

  1. 业务依赖版本集中定义,避免散落在每个模块。
  2. Java 编译版本写在父 POM。
  3. 不把账号密码写进 properties

4. 坐标系统与版本语义

SNAPSHOT vs RELEASE

类型 示例 语义 使用场景
SNAPSHOT 1.0.0-SNAPSHOT 开发快照,可能被覆盖 内部开发联调
RELEASE 1.0.0 稳定发布,不应被覆盖 正式发布、生产依赖

SNAPSHOT 依赖会被 Maven 按更新策略检查远程仓库,RELEASE 版本默认认为不可变。因此生产系统应依赖 RELEASE,不应依赖 SNAPSHOT。

语义化版本

推荐格式:

text 复制代码
主版本.次版本.修订版本
MAJOR.MINOR.PATCH
变化 示例 含义
PATCH 1.0.0 -> 1.0.1 Bug 修复,兼容
MINOR 1.0.0 -> 1.1.0 新功能,兼容
MAJOR 1.0.0 -> 2.0.0 不兼容变更

5. 仓库管理

Maven 仓库是依赖和构建产物的存储位置。

仓库类型

类型 默认位置或地址 作用
本地仓库 ~/.m2/repository 缓存依赖,存放 mvn install 的产物
中央仓库 https://repo.maven.apache.org/maven2 官方公共依赖仓库
远程仓库 公司 Nexus/Artifactory 私有依赖、代理缓存、发布产物
镜像 阿里云、腾讯云等 加速中央仓库下载

依赖解析顺序

text 复制代码
本地仓库
  ↓ 未命中
远程仓库 / 镜像
  ↓ 下载
写入本地仓库

常见误区:

  1. 删除本地仓库可以解决缓存损坏,但会导致依赖重新下载。
  2. mirrorOf=* 会镜像所有仓库,可能影响公司私服发布。
  3. repositories 放在 POM 中会影响所有成员,应该谨慎添加。

6. 基础命令全流程

命令 做什么 是否会执行前置阶段
mvn validate 校验项目结构和配置
mvn compile 编译主代码
mvn test 编译并运行测试
mvn package 打包产物
mvn install 安装到本地仓库
mvn deploy 发布到远程仓库
mvn clean 删除 target/ clean 生命周期

示例:

bash 复制代码
cd maven-demo
mvn clean package

关键输出:

text 复制代码
[INFO] Reactor Summary for maven-demo 1.0.0-SNAPSHOT:
[INFO] maven-demo-bom ................................ SUCCESS
[INFO] maven-demo-api ................................ SUCCESS
[INFO] maven-demo-core ............................... SUCCESS
[INFO] maven-demo-plugin ............................. SUCCESS
[INFO] maven-demo-web ................................ SUCCESS

7. 实战 Demo:maven-hello-world

如果从零创建单模块项目,可按下面结构:

text 复制代码
maven-hello-world/
├── pom.xml
└── src/
    ├── main/java/com/example/App.java
    └── test/java/com/example/AppTest.java

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>maven-hello-world</artifactId>
  <version>1.0.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
</project>

App.java

java 复制代码
package com.example;

public class App {
    public static void main(String[] args) {
        System.out.println("Hello Maven");
    }
}

运行:

bash 复制代码
mvn clean package
java -cp target/maven-hello-world-1.0.0-SNAPSHOT.jar com.example.App

预期输出:

text 复制代码
Hello Maven

本仓库的综合 Demo 位于 maven-demo/,它是该单模块项目的企业化扩展版本。


8. 常见问题与避坑

问题 原因 解决方案
Source option 5 is no longer supported 编译插件默认源码版本太旧 配置 maven-compiler-pluginrelease
依赖下载很慢 访问中央仓库慢 配置镜像或公司私服代理
IDE 能运行,命令行不能运行 IDE 使用的 JDK/Maven 与终端不一致 对比 java -versionmvn -version
本地依赖一直不更新 SNAPSHOT 缓存或 metadata 问题 使用 mvn -U 或清理对应依赖目录
多人构建结果不同 Maven/JDK/settings 不一致 使用 Maven Wrapper 和统一父 POM

9. 专家面试题

Q1:Maven 的"约定优于配置"体现在哪里?

答:Maven 规定了标准目录结构、默认生命周期、默认插件绑定和默认产物位置。例如主代码默认在 src/main/java,测试代码默认在 src/test/javamvn package 默认会编译、测试并打包。这样团队不需要为每个项目重复定义构建脚本。它的代价是灵活性低于 Gradle,但换来更强的一致性。

Q2:为什么 Maven 坐标要有 groupId、artifactId、version 三个字段?

答:artifactId 只能描述模块名,无法区分不同组织的同名模块;version 用于区分同一模块的不同发布版本。三者组合后才能在仓库中唯一定位一个产物。实际依赖解析还会叠加 packaging/typeclassifier,但 GAV 是最核心的身份。

Q3:mvn installmvn deploy 的区别是什么?

答:install 把当前项目产物安装到本机 ~/.m2/repository,供本机其他项目依赖;deploy 把产物发布到远程仓库,供团队或 CI 使用。开发本地联调用 install,正式共享版本用 deploy

Q4:为什么生产不建议依赖 SNAPSHOT?

答:SNAPSHOT 是可变版本,同一个 1.0.0-SNAPSHOT 在不同时间可能对应不同内容,导致构建不可复现。生产发布应依赖不可变 RELEASE 版本,并配合制品仓库权限禁止覆盖。


10. 入门篇扩展核查:必须补齐的基础知识

10.1 Maven 不是"下载 jar 的工具"

很多初学者把 Maven 理解成"自动下载 jar 包"。这个理解只覆盖了 Maven 的依赖管理能力,没有覆盖它的构建模型。

Maven 实际包含四层能力:

层级 说明 示例
项目建模 描述项目身份、模块、依赖、插件、发布信息 pom.xml
依赖解析 从仓库解析直接依赖和传递依赖 mvn dependency:tree
构建执行 按生命周期执行插件 Goal mvn clean package
制品发布 把 JAR、源码包、Javadoc、POM 发布到仓库 mvn deploy

所以 Maven 的学习顺序不能只停留在 <dependency>。如果不知道生命周期和插件,就无法解释为什么 mvn package 会先编译、测试再打包;如果不知道仓库和发布,就无法解释公司内部 SDK 如何被其他项目依赖。

10.2 Super POM 与 Effective POM

每个 Maven 项目都会隐式继承 Super POM。Super POM 提供了一组基础默认值,例如中央仓库、默认构建目录、默认插件绑定等。

查看当前项目最终 POM:

bash 复制代码
cd maven-demo
mvn help:effective-pom

建议重点观察:

text 复制代码
<repositories>
<pluginRepositories>
<build>
<plugins>
<dependencyManagement>
<profiles>

排查经验:

  1. 你在当前 POM 找不到的插件配置,可能来自父 POM 或 Super POM。
  2. 你以为没激活的 Profile,可能被 settings 或默认激活规则打开。
  3. 依赖版本不符合预期时,先看 Effective POM,再看依赖树。

10.3 Maven 标准目录为什么重要

Maven 通过标准目录实现"约定优于配置"。

目录 Maven 默认行为 常见错误
src/main/java 编译为主 classpath 把业务代码放到错误目录导致不编译
src/main/resources 复制到 target/classes 配置文件没进包
src/test/java 编译为测试 classpath 测试代码引用主代码失败
src/test/resources 复制到 target/test-classes 测试找不到测试配置
target 构建输出目录 手工修改 target 文件后被 clean 删除

验证:

bash 复制代码
cd maven-demo
mvn -pl maven-demo-core clean package
find maven-demo-core/target -maxdepth 3 -type f

你会看到:

text 复制代码
target/classes/build-info.properties
target/maven-demo-core-1.0.0-SNAPSHOT.jar
target/surefire-reports/...

10.4 archetype 创建项目

Maven archetype 是项目模板机制,适合快速创建标准项目。

bash 复制代码
mvn archetype:generate \
  -DgroupId=com.example \
  -DartifactId=maven-hello-world \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DinteractiveMode=false

创建后建议立即检查:

bash 复制代码
cd maven-hello-world
mvn test
mvn package

注意:archetype 生成的模板可能比较旧,例如 JUnit 版本、Java 编译版本不符合现代项目要求。生成后要升级 maven-compiler-plugin、JUnit 和编码配置。

10.5 本地仓库路径如何映射

依赖坐标:

text 复制代码
org.apache.commons:commons-lang3:3.14.0

本地仓库路径:

text 复制代码
~/.m2/repository/org/apache/commons/commons-lang3/3.14.0/

文件通常包括:

text 复制代码
commons-lang3-3.14.0.jar
commons-lang3-3.14.0.pom
_remote.repositories
*.sha1

如果依赖损坏,可以只删除对应版本目录,而不是删除整个 ~/.m2/repository

10.6 Maven 离线模式

离线模式只使用本地仓库,不访问远程仓库:

bash 复制代码
mvn -o package

适用场景:

  1. CI 缓存已预热。
  2. 内网环境暂时不能访问外部仓库。
  3. 验证项目是否具备可复现构建能力。

如果缺依赖,离线模式会失败。可以先执行:

bash 复制代码
mvn dependency:go-offline

10.7 IDE 导入 Maven 项目的核查点

在 IntelliJ IDEA 中导入 Maven 项目后,应检查:

检查项 正确状态
Project SDK JDK 17 或更高
Maven home 与命令行 Maven 版本一致
User settings file 指向正确 settings.xml
Local repository 与命令行一致
Profiles dev/test/prod 是否按需激活
Importing JVM 不要使用过旧 JDK

命令行能构建但 IDE 报错,优先比较 IDEA Maven 设置和 mvn -version

10.8 入门阶段实操任务

任务 命令 验收标准
查看 Maven 版本 mvn -version Maven 3.9+
查看 Effective POM mvn help:effective-pom 能找到插件和依赖管理
构建 API 模块 mvn -pl maven-demo-api test 测试通过
查看本地仓库 ls ~/.m2/repository/com/example/maven/demo 能找到安装后的 Demo 产物
离线构建 mvn -o package 本地依赖齐全时成功

10.9 入门篇新增面试题

Q5:Super POM 的作用是什么?

答:Super POM 是所有 Maven 项目隐式继承的基础 POM,提供默认仓库、默认构建目录、默认插件配置等。它让一个最小 POM 也能执行标准生命周期。排查真实构建行为时,应通过 Effective POM 查看 Super POM、父 POM、当前 POM 和 Profile 合并后的结果。

Q6:为什么不建议把本地 jar 用 system scope 引入?

答:system scope 依赖不可传递,依赖路径通常写死在本机文件系统中,CI 和其他开发者机器上很容易失败。正确做法是把 jar 发布到 Nexus/Artifactory,或者至少使用 mvn install:install-file 安装到本地仓库并记录来源。

Q7:Maven 本地仓库可以直接删除吗?

答:可以,但不建议作为第一选择。删除整个仓库会导致所有依赖重新下载,耗时且可能受网络影响。更合理的方式是删除损坏依赖的具体版本目录,或者使用 mvn -U 强制更新 SNAPSHOT。

相关推荐
Trival_dream7 小时前
应用与实例的关系
java·docker·kubernetes
无籽西瓜a7 小时前
【西瓜带你学Kafka | 第六期】Kafka 生产确认、消费 API 与分区分配策略(文含图解)
java·分布式·后端·kafka·消息队列·mq
子木HAPPY阳VIP7 小时前
Tomcat 9 + JSP 中文乱码终极解决方案(完整版可复制)
java·开发语言·docker·tomcat·jsp
郝学胜-神的一滴7 小时前
干货版《算法导论》 02 :算法效率核心解密
java·开发语言·数据结构·c++·python·算法
布吉岛的石头7 小时前
Java 岗,面试常问 100 题(精简版)
java·开发语言·面试
sinat_255487817 小时前
收藏品·学习笔记
java·javascript·windows·学习·microsoft
一碗面4217 小时前
Spring AI 多模态能力全景
java·spring·spring ai
信徒_7 小时前
服务治理技术选型
java