乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 介绍与核心概念

    • Maven是什么
    • 约定优于配置
  • 第2章 安装与配置

    • 安装与验证
    • settings.xml
    • 本地仓库与镜像
  • 第3章 POM与项目坐标

    • POM
    • GAV坐标
    • packaging
  • 第4章 标准目录布局

    • 标准目录布局
  • 第5章 依赖机制

    • dependencies
    • scope
    • 依赖传递
    • 依赖冲突与调解
    • exclusions
    • optional
    • dependencyManagement
  • 第6章 仓库

    • 仓库体系
    • 本地仓库
    • 远程仓库与镜像
    • 私服
  • 第7章 构建生命周期

    • 生命周期概述
    • clean 生命周期
    • default 生命周期
    • site 生命周期
    • 生命周期与插件绑定
  • 第8章 插件

    • 插件概述
    • maven-compiler-plugin
    • maven-surefire-plugin
    • maven-war-plugin
  • 第9章 继承与聚合

    • parent继承
    • 聚合
    • BOM
    • properties
  • 第10章 属性与资源过滤

    • 资源过滤
    • Profile
  • 第11章 常用命令

    • mvn compile
    • mvn test
    • mvn package
    • mvn clean
    • mvn install
    • mvn dependency:tree
  • 第12章 常见问题与最佳实践

    • 依赖冲突排查
    • 最佳实践

POM

本章承接"安装与配置"三部曲,正式进入 Maven 的项目核心。如果说安装和环境配置解决了"Maven 怎么跑"的问题,那么 POM 就是解决"项目是什么"的问题——它是 Maven 理解项目的唯一入口。


核心机制

项目对象模型(POM)是 Maven 中工作的基本单元。它是项目的 XML 表示,包含构建项目所需的全部信息。这意味着:

  1. 没有 POM,Maven 不工作。你在任何目录执行 mvn 命令,Maven 首先要找到 pom.xml,否则报错
  2. POM 是项目的"唯一真相源"。项目的名字、版本、依赖、构建方式,全部以 POM 为准,不以 IDE 的配置为准
  3. POM 是"声明式"的。你告诉 Maven"我想要什么",而不是"怎么做"。具体怎么做,由 Maven 根据 POM 的声明自动推导

POM 是项目的"DNA"

如果把一个 Maven 项目比作一个生物体,那么 pom.xml 就是它的 DNA 序列:

生物 DNAPOM 对应作用
物种标识基因groupId + artifactId + version唯一标识这个项目是谁
遗传信息dependencies这个项目"继承"了哪些外部能力
细胞结构build / plugins这个项目怎么"生长"(编译、打包)
环境适应性profiles在不同环境下(开发/测试/生产)的不同表现

就像 DNA 决定了生物的所有特征,POM 决定了项目的所有构建行为。两个项目的 POM 如果完全一样,那么无论谁在什么机器上构建,产物都完全一致——这就是 Maven 追求的可复现构建(Reproducible Build)。

modelVersion:POM 的"语法版本"

每个 pom.xml 的根元素 <project> 下,第一个子元素必须是 <modelVersion>。它表示当前 POM 文件遵循的 POM 模型版本,不是项目的版本。

<modelVersion>4.0.0</modelVersion>
  • Maven 2.x、3.x 统一使用 4.0.0,这是 2009 年定下的标准,至今未变
  • 它告诉 Maven 引擎:"请用 4.0.0 版本的规则来解析这个文件"
  • 如果写错(如 4.0 或 3.0.0),Maven 会拒绝解析,直接报错

可以把 modelVersion 理解为 POM 文件的"语法版本",类似 HTML 的 <!DOCTYPE html>。它与你项目的业务版本(1.0.0)完全无关。

最小 POM:Maven 的"最低生存需求"

一个合法的 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
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.feixiang</groupId>
    <artifactId>minimal-demo</artifactId>
    <version>1.0.0</version>
</project>

这个最小 POM 已经足以让 Maven 识别项目并执行基本构建。Maven 会为缺失的元素填充**超级 POM(Super POM)**中的默认值:

  • packaging 默认为 jar
  • sourceDirectory 默认为 src/main/java
  • testSourceDirectory 默认为 src/test/java
  • outputDirectory 默认为 target/classes

超级 POM 是 Maven 内置的一个"隐形模板",所有项目的 POM 都隐式继承它。它定义了 Maven 的"约定"默认值,是"约定优于配置"思想的工程实现。


图示

上图展示了 POM 的双层继承结构:项目 POM 只声明项目的独特信息(坐标、依赖),而所有"通用规则"(目录结构、插件绑定)由超级 POM 提供。两者合并后,形成完整的构建配置。这也是 Maven 配置精简的根本原因——你不需要重复声明行业共识。


完整示例

场景

飞翔科技要启动一个新项目 employee-system(员工信息管理系统)。CTO 大翔要求项目必须从零开始建立标准的 Maven 结构,方便后续团队协作。架构师白歌负责创建初始 POM,后端小崔负责验证构建。

操作前:空目录

小崔在本地创建了一个空目录:

C:\projects\employee-system/

里面什么都没有。白歌说:"先别急着写 Java 代码,先把 POM 建好。POM 是项目的地基。"

操作步骤

步骤 1:创建最小 POM

白歌在 employee-system/ 目录下创建 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.feixiang</groupId>
    <artifactId>employee-system</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>员工信息管理系统</name>
    <description>飞翔科技内部员工信息管理与查询系统</description>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.21</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

步骤 2:创建标准目录结构

小崔根据 POM 的隐式约定,创建标准目录:

mkdir -p src/main/java/com/feixiang/employee
mkdir -p src/main/resources
mkdir -p src/test/java/com/feixiang/employee
mkdir -p src/test/resources

目录结构变为:

employee-system/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── feixiang/
│   │   │           └── employee/
│   │   └── resources/
│   └── test/
│       ├── java/
│       └── resources/

步骤 3:验证构建

小崔执行编译:

mvn compile

预期输出:

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------< com.feixiang:employee-system >------------------
[INFO] Building 员工信息管理系统 1.0.0-SNAPSHOT
[INFO]   from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.3.1:resources (default-resources) @ employee-system ---
[INFO] Copying 0 resource from src\main\resources to target\classes
[INFO] --- maven-compiler-plugin:3.11.0:compile (default-compile) @ employee-system ---
[INFO] Changes detected - recompiling the module! :source
[INFO] Compiling 0 source files to target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.345 s
[INFO] Finished at: 2024-01-15T09:30:00+08:00
[INFO] ------------------------------------------------------------------------

操作结果及分析

输出项含义来源
com.feixiang:employee-system项目坐标pom.xml 中的 GAV
员工信息管理系统项目可读名称pom.xml 中的 <name>
jar打包类型pom.xml 中的 <packaging>
maven-resources-plugin:3.3.1资源复制插件超级 POM 默认绑定
maven-compiler-plugin:3.11.0编译插件超级 POM 默认绑定
target\classes编译输出目录超级 POM 默认路径

注意:小崔没有在 pom.xml 里写任何关于"资源复制"或"编译器版本"的配置,但 Maven 自动调用了 maven-resources-plugin 和 maven-compiler-plugin。这就是超级 POM 的力量——它预定义了标准生命周期与插件的绑定关系。


易错点与常见问题

误区一:modelVersion 写成项目版本

错误配置:

<modelVersion>1.0.0</modelVersion>   <!-- ❌ 这是项目版本,不是模型版本 -->

后果:Maven 解析 POM 时,发现 modelVersion 不是它认识的 4.0.0,直接报错:

[ERROR] 'modelVersion' must be one of 4.0.0 but is '1.0.0'.

纠正:modelVersion 永远是 4.0.0,与项目业务版本无关:

<modelVersion>4.0.0</modelVersion>          <!-- ✅ POM 模型版本 -->
<version>1.0.0-SNAPSHOT</version>           <!-- ✅ 项目业务版本 -->

误区二:省略 XML 命名空间

错误配置:

<project>   <!-- ❌ 缺少 xmlns 命名空间 -->
    <modelVersion>4.0.0</modelVersion>
    ...
</project>

后果:某些严格校验的 Maven 插件(如 maven-enforcer-plugin)或 CI 环境会报 Schema 验证错误。虽然 Maven 核心引擎有时能容忍,但这是不规范的写法。

纠正:始终携带完整的命名空间声明:

<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 只是"依赖列表"

错误认知:"pom.xml 不就是写依赖的地方吗?别的标签我不关心。"

纠正:dependencies 只是 POM 的冰山一角。一个完整的 POM 还管理着:

  • 项目身份:groupId、artifactId、version、name、description
  • 构建行为:build、plugins、pluginManagement
  • 环境适配:profiles(开发/测试/生产差异化配置)
  • 项目关系:parent(继承)、modules(聚合)、dependencyManagement
  • 元信息:licenses、developers、scm(版本控制地址)

POM 是项目的完整声明,依赖只是其中一部分。如果你只把 POM 当依赖清单用,就错过了 Maven 管理项目关系的强大能力。


小结

POM(Project Object Model)是 Maven 的工作基本单元,pom.xml 是项目的"DNA"和"唯一真相源"。它通过 modelVersion 声明文件语法版本,通过 GAV 坐标声明项目身份,通过 dependencies 声明外部依赖,其余构建规则由超级 POM 提供默认值。理解 POM 的层次结构(超级 POM + 项目 POM),是理解继承、聚合、依赖管理等高级机制的基础。

本章与全局的关系:本章建立了项目的"身份档案"。下一章"GAV 坐标"将深入讲解 groupId、artifactId、version 三要素,揭示 Maven 如何通过"坐标系统"在茫茫仓库中唯一锁定一个项目。

下一页
GAV坐标