全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-23 12 分钟 ✍️ juanwangdev

pom.xml 基础结构

pom.xml(Project Object Model)是 Maven 项目的核心配置文件。所有 Maven 构建命令都读取 pom.xml,根据其中的配置执行编译、测试、打包、发布等任务。理解 pom.xml 的结构是掌握 Maven 的基础。

为什么需要 pom.xml

Maven 项目统一配置

XML
传统项目的问题:

Ant 项目:
- build.xml 定义构建流程
- 手动管理依赖目录
- 不同项目配置差异大

手动管理:
- 项目配置分散:源码目录、输出目录、依赖等
- 团队成员配置可能不一致
- 新项目需要从头配置

Maven 解决方案:
- pom.xml 统一管理所有项目信息
- 标准化的项目结构
- 一个文件包含所有构建配置

pom.xml 包含的内容

配置类别包含内容
项目标识groupId、artifactId、version(坐标)
项目信息名称、描述、URL、开发者
依赖管理项目依赖的第三方库
构建配置源码目录、输出目录、插件配置
环境配置Profile 多环境配置
继承关系父 POM、聚合模块

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">

  <modelVersion>4.0.0</modelVersion>

  <!-- 项目坐标:唯一标识项目 -->
  <groupId>com.example</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>

</project>

必要元素说明

元素说明是否必填示例
modelVersionPOM 模型版本必填固定值 4.0.0
groupId组织标识必填com.example
artifactId项目名称必填my-app
version版本号必填1.0.0

modelVersion 为什么固定 4.0.0

XML
modelVersion 表示 POM 文件的格式版本:
- 4.0.0 是当前 Maven 使用的 POM 格式版本
- Maven 3.x 只支持 4.0.0
- 不要改这个值,固定写 4.0.0

如果写成其他版本:
- Maven 无法解析
- 构建失败

一个能运行的最小项目

XML
创建最小 Maven 项目:

步骤1:创建项目目录
mkdir my-app
cd my-app

步骤2:创建 pom.xml(上面的最小结构)

步骤3:创建源码目录
mkdir -p src/main/java/com/example

步骤4:创建 Java 文件
src/main/java/com/example/App.java:
package com.example;
public class App {
    public static void main(String[] args) {
        System.out.println("Hello Maven!");
    }
}

步骤5:构建
mvn compile

步骤6:运行
mvn exec:java -Dexec.mainClass=com.example.App
输出:Hello Maven!

这就是一个完整的 Maven 项目,只需要最小 pom.xml + 标准目录结构。

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">

  <modelVersion>4.0.0</modelVersion>

  <!-- ====================项目坐标 ==================== -->
  <groupId>com.example</groupId>
  <artifactId>my-web-app</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>war</packaging>  <!-- 打包类型 -->

  <!-- ==================== 项目信息 ==================== -->
  <name>My Web Application</name>
  <description>示例 Web 项目</description>
  <url>https://example.com/my-web-app</url>
  <inceptionYear>2024</inceptionYear>

  <!-- 组织信息 -->
  <organization>
    <name>Example Company</name>
    <url>https://example.com</url>
  </organization>

  <!-- 开发者信息 -->
  <developers>
    <developer>
      <id>developer1</id>
      <name>张三</name>
      <email>zhangsan@example.com</email>
      <organization>Example Company</organization>
    </developer>
  </developers>

  <!-- 许可证 -->
  <licenses>
    <license>
      <name>Apache License 2.0</name>
      <url>https://www.apache.org/licenses/LICENSE-2.0</url>
    </license>
  </licenses>

  <!-- ==================== 属性定义 ==================== -->
  <properties>
    <!-- Java 版本 -->
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <!-- 依赖版本 -->
    <spring.version>5.3.20</spring.version>
    <junit.version>4.13.2</junit.version>
    <servlet.version>4.0.1</servlet.version>
  </properties>

  <!-- ==================== 依赖管理 ==================== -->
  <dependencyManagement>
    <dependencies>
      <!-- 统一管理版本 -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-framework-bom</artifactId>
        <version>${spring.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <!-- ==================== 依赖声明 ==================== -->
  <dependencies>
    <!-- Spring Web -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <!-- 版本由 BOM 管理 -->
    </dependency>

    <!-- Servlet API -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>

    <!-- JUnit 测试 -->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <!-- ==================== 构建配置 ==================== -->
  <build>
    <!-- 最终产物名称 -->
    <finalName>${project.artifactId}</finalName>

    <!-- 资源文件配置 -->
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>  <!-- 启用变量替换 -->
      </resource>
    </resources>

    <!-- 插件配置 -->
    <plugins>
      <!-- 编译插件 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <encoding>${project.build.sourceEncoding}</encoding>
        </configuration>
      </plugin>

      <!-- WAR 打包插件 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>3.3.2</version>
      </plugin>

      <!-- 测试插件 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
      </plugin>
    </plugins>
  </build>

  <!-- ==================== 多环境 Profile ==================== -->
  <profiles>
    <profile>
      <id>dev</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <env>dev</env>
      </properties>
    </profile>

    <profile>
      <id>prod</id>
      <properties>
        <env>prod</env>
      </properties>
    </profile>
  </profiles>

</project>

POM 元素分类详解

类别元素说明必填
坐标groupId组织标识必填
artifactId项目名称必填
version版本号必填
packaging打包类型选填(默认jar)
信息name项目名称(显示名)选填
description项目描述选填
url项目网址选填
属性properties自定义属性选填
依赖dependencies依赖声明选填
dependencyManagement依赖版本管理选填
构建build构建配置选填
环境profiles多环境配置选填

packaging 打包类型

打包类型说明

packaging说明输出文件使用场景
jar(默认)Java 库打包*.jar普通Java 项目、库项目
warWeb应用打包*.warWeb 项目
pom聚合/父项目无产物多模块父项目
maven-pluginMaven插件*.jar开发 Maven 插件
ear企业应用*.earJava EE 应用
rar资源适配器*.rarJCA 资源适配器

不同打包类型的默认行为

XML
jar 打包(默认):
- package 阶段:生成 jar 文件
- 默认插件绑定:maven-jar-plugin

war 打包:
- package 阶段:生成 war 文件
- 默认插件绑定:maven-war-plugin
- Web 项目目录结构:
  src/main/webapp/(Web资源)

pom 打包:
- 不生成产物
- 用于父项目或聚合项目
- modules 元素定义子模块

packaging示例

XML
<!-- Java 库项目 -->
<packaging>jar</packaging>

<!-- Web 项目 -->
<packaging>war</packaging>

<!-- 父项目/聚合项目 -->
<packaging>pom</packaging>

POM 属性(properties)

属性的作用

XML
为什么使用 properties?

问题:版本号分散在各处
<dependency>
  <artifactId>spring-core</artifactId>
  <version>5.3.20</version>  ← 版号写在这里
</dependency>
<dependency>
  <artifactId>spring-context</artifactId>
  <version>5.3.20</version>  ← 又写在这里
</dependency>

升级版本时:
- 需要改多处
- 可能遗漏
- 版本可能不一致

解决:使用 properties
<properties>
  <spring.version>5.3.20</spring.version>
</properties>

<dependency>
  <artifactId>spring-core</artifactId>
  <version>${spring.version}</version>
</dependency>

升级时:改一处即可
<spring.version>5.3.21</spring.version>

常用属性定义

Bash
<properties>
  <!-- 编译相关 -->
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  <!-- 依赖版本 -->
  <spring.version>5.3.20</spring.version>
  <spring-boot.version>2.7.0</spring-boot.version>
  <junit.version>4.13.2</junit.version>
  <logback.version>1.2.11</logback.version>

  <!-- 自定义属性 -->
  <env>dev</env>
  <db.url>jdbc:mysql://localhost:3306/dev</db.url>
</properties>

内置属性

属性说明示例值
${project.groupId}项目 groupIdcom.example
${project.artifactId}项目 artifactIdmy-app
${project.version}项目版本1.0.0
${project.basedir}项目根目录/path/to/project
${project.build.directory}构建目录target
${project.build.sourceEncoding}源码编码UTF-8
${maven.compiler.source}Java源版本17
${maven.compiler.target}Java目标版本17

属性引用示例

XML
<build>
  <finalName>${project.artifactId}-${project.version}</finalName>
  <!-- 最终产物名:my-app-1.0.0.jar -->
</build>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-core</artifactId>
  <version>${spring.version}</version>
</dependency>

POM 继承机制

继承层次结构

XML
Maven POM 继承层次:

超级 POM(Maven 内置)
    ↓ 默认继承
父 POM(可选)
    ↓显式继承
项目 POM(pom.xml)
    ↓ 合并
有效 POM(Effective POM)

超级 POM

所有 pom.xml 都隐式继承超级 POM,超级 POM 定义了 Maven 的默认配置:

XML
超级 POM 提供的默认配置:

默认目录结构:
- src/main/java:源码目录
- src/main/resources:资源目录
- src/test/java:测试源码
- src/test/resources:测试资源
- target:输出目录

默认仓库:
- 中央仓库:https://repo.maven.apache.org/maven2

默认插件版本:
- maven-compiler-plugin
- maven-jar-plugin
- maven-surefire-plugin
- maven-clean-plugin
- maven-install-plugin
- maven-deploy-plugin
- maven-resources-plugin

显式继承父 POM

XML
<!-- 继承 Spring Boot 父 POM -->
<project>
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.0</version>
    <relativePath/>  <!-- 从仓库查找,不使用本地路径 -->
  </parent>

  <!-- 子项目只需声明 artifactId -->
  <artifactId>my-app</artifactId>
  <!-- groupId、version 继承自父 POM -->

</project>

继承的好处

特性说明
groupId 继承子项目可不声明,继承父项目
version 继承子项目可不声明,继承父项目版本
properties 继承父项目定义的属性子项目可用
dependencyManagement 继承父项目管理的依赖版本子项目可用
pluginManagement 继承父项目管理的插件配置子项目可用
配置合并子项目可覆盖父项目配置

父 POM 的 relativePath

XML
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.0</version>
  <!-- relativePath 配置 -->
  <relativePath/>  <!-- 从仓库查找,不使用本地路径 -->
</parent>

relativePath 说明

relativePath说明
省略默认查找父目录的 pom.xml
<relativePath/>(空)从仓库查找,不使用本地路径
<relativePath>../parent/pom.xml</relativePath>指定父 POM路径

多模块项目的父 POM

text
<!-- 父项目 pom.xml -->
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-project-parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>  <!-- 父项目必须是 pom -->

  <!-- 定义子模块 -->
  <modules>
    <module>module-a</module>
    <module>module-b</module>
    <module>module-c</module>
  </modules>

  <!-- 统一管理依赖版本 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.20</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

<!-- 子模块 module-a/pom.xml -->
<project>
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>com.example</groupId>
    <artifactId>my-project-parent</artifactId>
    <version>1.0.0</version>
  </parent>

  <artifactId>module-a</artifactId>  <!-- 只需声明 artifactId -->

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <!-- 版本继承 dependencyManagement -->
    </dependency>
  </dependencies>
</project>

有效 POM(Effective POM)

什么是有效 POM

text
有效 POM = 超级 POM +父 POM + 项目 POM

所有配置合并后的最终配置:
- 包含所有继承的配置
- 包含所有默认配置
- 包含项目显式配置

查看有效 POM

text
mvn help:effective-pom

输出示例:

text
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>my-app</artifactId>
  <version>1.0.0</version>

  <!-- 下面都是超级 POM 的默认配置 -->
  <repositories>
    <repository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <url>https://repo.maven.apache.org/maven2</url>
    </pluginRepository>
  </pluginRepositories>

  <build>
    <sourceDirectory>src/main/java</sourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>
    <outputDirectory>target/classes</outputDirectory>
    <testOutputDirectory>target/test-classes</testOutputDirectory>
    <directory>target</directory>

    <plugins>
      <!-- 所有默认插件配置 -->
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        ...
      </plugin>
      <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        ...
      </plugin>
      <!-- 其他插件 -->
    </plugins>
  </build>
</project>

有效 POM 的用途

text
用途1:查看最终配置
- 检查默认目录结构
- 检查默认插件版本
- 检查继承的配置

用途2:诊断问题
- 为什么某个插件版本不对?
- 为什么某个配置没生效?
- 查看合并结果

用途3:学习 Maven 默认配置
- 了解 Maven 内置的默认值
- 理解"约定优于配置"

POM 常见配置场景

场景1:Java 版本配置

text
<!-- 方式1:使用 properties -->
<properties>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
</properties>

<!-- 方式2:使用编译插件配置 -->
<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.8.1</version>
      <configuration>
        <source>17</source>
        <target>17</target>
      </configuration>
    </plugin>
  </plugins>
</build>

场景2:资源过滤配置

text
<!-- application.properties -->
app.version=${project.version}
app.name=${project.artifactId}

<!-- pom.xml 启用资源过滤 -->
<build>
  <resources>
    <resource>
      <directory>src/main/resources</directory>
      <filtering>true</filtering>  <!-- 启用变量替换 -->
    </resource>
  </resources>
</build>

构建后 application.properties:
app.version=1.0.0
app.name=my-app

场景3:最终产物名称

text
<build>
  <!-- 方式1:使用 artifactId -->
  <finalName>${project.artifactId}</finalName>
  <!-- 产物:my-app.jar -->

  <!-- 方式2:包含版本 -->
  <finalName>${project.artifactId}-${project.version}</finalName>
  <!-- 产物:my-app-1.0.0.jar -->

  <!-- 方式3:自定义名称 -->
  <finalName>my-application</finalName>
  <!-- 产物:my-application.jar -->
</build>

场景4:多环境配置

text
<profiles>
  <profile>
    <id>dev</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <db.url>jdbc:mysql://localhost:3306/dev</db.url>
    </properties>
  </profile>

  <profile>
    <id>prod</id>
    <properties>
      <db.url>jdbc:mysql://prod-server:3306/prod</db.url>
    </properties>
  </profile>
</profiles>

<!-- application.properties -->
database.url=${db.url}

构建:
mvn package -Pdev  → database.url=localhost
mvn package -Pprod → database.url=prod-server

POM 配置最佳实践

推荐做法

做法说明
使用 properties 统一版本版号集中管理,方便升级
groupId 用反向域名保证全球唯一性
version 用语义化版本主版本.次版本.增量版本
显式声明编码<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
复杂依赖用 dependencyManagement统一版本,避免冲突
多模块项目使用父 POM继承配置,减少重复

不推荐做法

做法问题
版本号分散升级麻烦,容易遗漏
SNAPSHOT 版本用于生产构建结果不稳定
省略 modelVersion必须写 4.0.0
packaging 不写默认 jar,Web项目需显式 war

常见问题

问题1:pom.xml 格式错误

text
报错:
[ERROR] Failed to execute goal ... 
Invalid POM: Parse error

原因:
- XML 格式错误
- 缺少必要元素
- 命名空间声明错误

解决:
1. 检查 XML 格式
2. 确保 modelVersion=4.0.0
3. 检查命名空间声明

问题2:继承父 POM找不到

text
报错:
[ERROR] Non-resolvable parent POM

原因:
- relativePath 配置错误
- 父 POM 版本不存在

解决:
1. 检查父 POM坐标
2. 检查 relativePath
3. 确保父 POM 已发布到仓库

问题3:属性引用不生效

text
问题:${spring.version} 没有替换

原因:
- properties 未定义
- 资源过滤未启用

解决:
1. 检查 properties 定义
2. 启用资源过滤:<filtering>true</filtering>

要点总结

  1. 最小 POM:modelVersion + groupId + artifactId + version
  2. modelVersion 固定4.0.0:不要改这个值
  3. packaging 默认jar:Web 项目需显式 war
  4. properties 统一版本:方便管理和升级
  5. 所有 POM 继承超级 POM:内置默认配置
  6. 显式继承父 POM:复用配置,统一管理
  7. effective-pom 查看完整配置:包含所有继承和默认配置
  8. dependencyManagement 统一版本:多模块项目必备
  9. 资源过滤启用变量替换:${project.version} 等可替换

📝 发现内容有误?点击此处直接编辑

← 上一篇 约定优于配置原则
下一篇 → 属性与变量替换
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库