Maven pom.xml文件详解
pom指的是project object model,又叫项目对象模型。Maven的pom文件是一个XML文件,用于描述项目的各种属性、依赖和构建信息,包括项目的名称、版本、许可证、作者、描述、依赖关系、构建过程、插件等。总的来说,POM文件是Maven工程的基本工作单元,它包含了项目的所有必要信息,使得Maven能够自动化地构建和管理项目。在Maven中,标签用于定义项目的依赖关系,可以将项目所
一、pom.xml 简介
pom.xml(Project Object Model)是Maven项目的核心配置文件,定义了项目的所有信息,包括依赖、插件、构建配置等。它是Maven项目的基础,通常被称为项目的蓝图。其核心概念与文件位置如下:
- 位置:位于Maven项目的根目录
- 目的:描述项目、管理依赖、定义构建过程
- 继承机制:支持父子POM继承,实现配置复用
二、pom.xml 文件结构
一个基本的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>
<!-- 父项目坐标属性 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath>/home/mymodule</relativePath>
</parent>
<!-- 当前项目基本属性 -->
<groupId>com.njh</groupId>
<artifactId>Njh-Cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Njh-Cloud</name>
<description>Njh-Cloud</description>
<packaging>pom</packaging>
<!-- 当前项目下的子模块配置 -->
<modules>
<module>njh-gateway</module>
</modules>
<!-- 项目常量属性设置 -->
<properties>
<java.version>1.8</java.version>
</properties>
<!-- 项目依赖管理 -->
<dependencyManagement>
<dependencies>
<!-- SpringCloud 微服务 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 项目依赖定义 -->
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
</dependencies>
<!-- 项目构建信息 -->
<build>
<!-- 插件管理 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
<!-- 资源管理 -->
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 关闭过滤 -->
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/webapp/</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
<!-- 引入所有 匹配文件进行过滤 -->
<includes>
<include>application*</include>
<include>bootstrap*</include>
<include>logback*</include>
</includes>
<!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
<filtering>true</filtering>
</resource>
</resources>
</build>
<!-- 项目环境信息 -->
<profiles>
<profile>
<!-- 本地开发环境 -->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<!-- 默认激活dev环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prd</id>
<properties>
<profiles.active>prd</profiles.active>
</properties>
</profile>
</profiles>
<!-- 项目仓库信息 -->
<repositories>
<repository>
<id>public</id>
<name>nexus</name>
<url>https://mirrors.njh.cloud.com/repository/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<!-- 项目插件仓库信息 -->
<pluginRepositories>
<pluginRepository>
<id>public</id>
<name>nexus</name>
<url>https://mirrors.njh.cloud.com/repository/maven/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
2.1 主要组成部分详解
2.1.1 父项目坐标属性
在Maven中使用<parent>标签是为了在多模块项目中共同管理依赖,可以让多个模块之间共享依赖关系,从而避免了重复的依赖定义。通过<parent>标签中的<groupId>、<artifactId>和<version>元素来指定父项目的坐标,子项目就可以通过该坐标找到父项目并自动继承父项目的pom文件中定义的相关依赖,然后子项目就可以不用重复去声明父项目中已存在的依赖,可以直接使用父项目中的依赖。
<parent>
<!-- 父项目的群组标识符 -->
<groupId>org.springframework.boot</groupId>
<!-- 父项目的项目名标识符 -->
<artifactId>spring-boot-starter-parent</artifactId>
<!-- 父项目的版本号标识符 -->
<version>3.2.1</version>
<!-- 用于指示Maven在查找父级POM文件时应该搜索的相对路径 -->
<relativePath>/home/mymodule</relativePath>
</parent>
- 父POM通常用于:
- 统一版本管理
- 共享配置
- 定义公共插件
2.1.2 项目基本属性
用于设置当前项目的一些基本信息,通过<groupId>、<artifactId>和<version>元素来指定当前项目的坐标;<name>用来设置项目名称;<description>用来设置项目的描述信息;<url>用来设置项目的主也url地址;<packaging>用来设置项目的构建类型,如:jar、war、pom等。
<groupId>com.njh</groupId>
<artifactId>Njh-Cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Njh-Cloud</name>
<description>Njh-Cloud</description>
<url>https://gitee.com/Njh-Cloud</url>
<packaging>pom</packaging>
- groupId + artifactId + version = 依赖的唯一标识
- 版本约定:
- SNAPSHOT:开发版本(可覆盖)
- RELEASE:发布版本(不可修改)
- 语义化版本:主版本.次版本.修订版本
2.1.3 项目下的子模块配置
在Maven中,<modules>标签用于定义项目的模块。一个Maven项目可以包含多个模块,每个模块可以被视为一个独立的子项目。通过使用<modules>标签,可以将一个大项目拆分成多个小模块,每个模块都有自己的构建过程和依赖关系,从而提高项目的可维护性和可重用性。
<modules>
<module>njh-gateway</module>
<module>njh-common</module>
</modules>
2.1.4 项目常量属性设置
在Maven中,<properties>标签中用于定义项目的常量属性,这些常量属性可以在整个项目中被共享和重用,从而简化了项目的配置和管理。每个属性都包含一个id和一个值,在使用时通过${id}就能获取到设置的属性值。
<properties>
<!-- 系统属性 -->
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<!-- 自定义属性 -->
<spring.version>5.3.20</spring.version>
<junit.version>5.8.2</junit.version>
<!-- 环境属性 -->
<env>dev</env>
</properties>
<!-- 使用上面的属性 -->
<version>${java.version}</version>
2.1.5 项目依赖管理
在Maven中,<dependencyManagement>标签用于管理项目中的依赖关系,确保所有子模块共享相同的依赖版本。通过在<dependencyManagement>标签中添加需要共用的依赖,在该项目下的所有子模块会自动引入相同的依赖,可以避免在每个子模块中重复定义相同的依赖,提高了项目构建的效率和一致性。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>version</version>
</dependency>
</dependencies>
</dependencyManagement>
2.1.6 项目依赖定义
在Maven中,<dependencies>标签用于定义项目的依赖关系,可以将项目所需的依赖库添加到项目中,并确保这些依赖被正确地管理和使用。每个依赖都是使用<dependency>标签定义的,<dependency>标签中常用的属性有:
<groupId>:依赖库的唯一标识符,通常是组织或项目的唯一标识符。<artifactId>:依赖库的唯一标识符,通常是项目或库的唯一标识符。<version>:依赖库的版本号。<scope>:依赖项的作用范围 ,包括compile、provided、runtime、test、system、optional。<optional>:标注依赖是否传递。默认值为 false,表示可以将该依赖向下传递给其他依赖了该项目的项目。设置成true,则不会向下传递。<exclusions>:排除项目中引入的依赖中所包含的某些间接依赖。
<dependencies>
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<version>version</version>
<scope>compile</scope>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>groupid</groupId>
<artifactId>artifactid</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
scope 依赖项常用的适用范围如下:
- compile:缺省值,表示所有阶段(编译、测试、运行)可用,该依赖包需要全程存在会随着项目一起发布。
- provided:表示只在提供依赖的环境中是可用的,也就是在编译、测试时需要,运行时不需要,该依赖不会被打包到项目中;
- runtime:表示只在运行时可用,该依赖会打包到项目中;
- test:表示只在测试期间是可用的,该依赖不会被打包到项目中;
- system:表示只能在系统类路径中找到,不会在Repository中查找它;
2.1.7 项目构建信息
在Maven中,<build>标签用于配置项目的构建过程。它包含了一系列的子标签,用于定义项目的构建策略和任务。常用的字标签有:
<plugins>:用于定义Maven插件的列表。Maven插件可以用来执行各种任务,例如编译代码、运行测试、打包和发布项目等。<pluginManagement>:用于定义项目的构建插件的列表,以及这些插件的配置。<resources>:用于定义资源的配置,例如在构建过程中要处理的属性文件或资源文件。<testResources>:类似于<resources>,但是用于配置测试资源,例如在测试过程中要处理的属性文件或资源文件。<sourceDirectory>:用于指定项目的源代码目录。<outputDirectory>:用于指定项目的输出目录,例如生成的JAR文件或WAR文件。<filters>:用于定义项目的过滤器,例如在构建过程中要应用的属性文件过滤器。<finalName>:用于指定项目的最终名称,例如生成的JAR文件的名称。
<build>
<plugins></plugins>
<resources></resources>
<testResources></testResources>
<sourceDirectory></sourceDirectory>
<outputDirectory></outputDirectory>
<filters></filters>
<finalName></finalName>
<pluginManagement></pluginManagement>
</build>
2.1.8 项目环境信息
在Maven中,<profiles>标签用于定义项目的构建环境的配置,它允许你为不同的构建环境或目标提供不同的配置。通过不同的<profile>标签来定义不同的环境配置,在<profile>标签里面包含以下部分:
<id>:配置文件的唯一标识符。<activation>:用于激活配置文件的逻辑。例如,使用<activeByDefault>属性来指定默认激活的配置文件。<properties>: 用于存储配置文件中使用的属性。<build>: 用于定义配置文件中的构建任务和插件。
<profiles>
<profile>
<!-- 本地开发环境 -->
<id>dev</id>
<properties>
<profiles.active>dev</profiles.active>
</properties>
<!-- 默认激活dev环境 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<!-- 生产环境 -->
<id>prd</id>
<properties>
<profiles.active>prd</profiles.active>
</properties>
</profile>
</profiles>
2.1.9 项目仓库信息
在Maven中,<repositories>标签用于配置项目所需的依赖库的位置,使得项目能够方便地获取和管理依赖。通过配置不同的仓库,可以轻松地在不同的环境中使用不同的依赖库,从而增加了项目的灵活性和可移植性。其中<repository>标签包含以下部分:
<id>:仓库的唯一标识符。<url>:仓库的URL地址。<releases>:用于配置仓库中发布的版本。如果<releases>标签被包含,那么Maven会在这个仓库中搜索并下载项目所需的依赖库。<snapshots>:用于配置仓库中快照版本的位置。如果<snapshots>标签被包含,那么Maven会在这个仓库中搜索并下载项目所需的快照版本。
<repositories>
<repository>
<id>snapshots</id>
<url>http://repo.maven.apache.org/maven-snapshots/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
<repository>
<id>releases</id>
<url>http://repo.maven.apache.org/maven-releases/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
2.1.10项目插件仓库信息
在Maven中,<pluginRepositories>标签用于配置项目所需的插件库的位置,与<repositories>标签功能基本相同,主要的区别是为了获取和管理Maven插件和插件依赖的。
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://repo.maven.apache.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
2.2 高级特性
2.2.1 资源过滤与占位符替换
在资源文件中使用${}占位符,Maven会自动替换:
# src/main/resources/app.properties
app.version=${project.version}
build.time=${timestamp}
database.url=${database.url}
2.2.2 构建生命周期配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase> <!-- 在package阶段执行 -->
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
2.2.3 自定义属性文件
<build>
<filters>
<filter>src/main/filters/dev.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
三、pom.xml 优先级机制
Maven 的配置优先级系统决定了当存在多个配置来源时,哪些配置会最终生效。
3.1 配置层次结构
Maven 配置按照从低到高的优先级层次:
项目POM (最低)
↓
父POM
↓
项目Profile
↓
用户Settings (~/.m2/settings.xml)
↓
全局Settings (M2_HOME/conf/settings.xml)
↓
命令行参数 (最高)
↓
系统属性/环境变量 (实时覆盖)
3.2 优先级规则
3.2.1 同级配置的覆盖规则
在同一个 POM 文件内,后面出现的配置会覆盖前面的配置:
<!-- 示例:后面的依赖会覆盖前面的相同依赖 -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-a</artifactId>
<version>1.0</version> <!-- 被下面的 2.0 覆盖 -->
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-a</artifactId>
<version>2.0</version> <!-- 生效版本 -->
</dependency>
</dependencies>
3.2.2 继承链优先级
子项目会继承并可以覆盖父项目的配置:
-
父POM (parent/pom.xml)
<project> <groupId>com.company</groupId> <artifactId>parent</artifactId> <version>1.0</version> <packaging>pom</packaging> <properties> <java.version>11</java.version> <!-- 默认值 --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.0</version> <!-- 管理版本 --> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build> </project> -
子POM (child/pom.xml) - 覆盖示例
<project> <parent> <groupId>com.company</groupId> <artifactId>parent</artifactId> <version>1.0</version> </parent> <artifactId>child</artifactId> <properties> <java.version>17</java.version> <!-- 覆盖父POM的11 --> </properties> <dependencies> <!-- 使用父POM管理的版本 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <!-- 不需要指定version,使用父POM的5.2.0 --> </dependency> <!-- 子POM可以覆盖版本 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>5.3.0</version> <!-- 直接指定,优先级最高 --> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <!-- 继承父POM的配置,但可以添加额外配置 --> <configuration> <encoding>GBK</encoding> <!-- 增加配置 --> <!-- source和target继承父POM,但使用子POM的java.version属性 --> </configuration> </plugin> </plugins> </build> </project>
3.2.3 Settings.xml 的覆盖机制
-
全局Settings (conf/settings.xml)
<settings> <mirrors> <mirror> <id>global-mirror</id> <url>http://global-repo.com</url> <mirrorOf>*</mirrorOf> </mirror> </mirrors> <profiles> <profile> <id>global-profile</id> <properties> <global.property>value1</global.property> </properties> </profile> </profiles> <activeProfiles> <activeProfile>global-profile</activeProfile> </activeProfiles> </settings> -
用户Settings (~/.m2/settings.xml) - 优先级更高
<settings> <!-- 覆盖全局镜像 --> <mirrors> <mirror> <id>user-mirror</id> <url>http://user-repo.com</url> <mirrorOf>*</mirrorOf> <!-- 这个配置生效 --> </mirror> </mirrors> <profiles> <profile> <id>user-profile</id> <properties> <user.property>value2</user.property> <global.property>overridden</global.property> <!-- 覆盖全局属性 --> </properties> </profile> </profiles> <activeProfiles> <activeProfile>user-profile</activeProfile> <!-- 用户Profile生效 --> </activeProfiles> </settings>
3.2.4 Profile 激活优先级
多个Profile激活时的合并和覆盖规则:
<!-- settings.xml -->
<profiles>
<profile>
<id>settings-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<db.host>localhost</db.host>
<db.port>3306</db.port>
</properties>
<repositories>
<repository>
<id>settings-repo</id>
<url>http://settings-repo</url>
</repository>
</repositories>
</profile>
</profiles>
<!-- pom.xml -->
<profiles>
<profile>
<id>pom-profile</id>
<activation>
<property>
<name>env</name>
<value>prod</value>
</property>
</activation>
<properties>
<db.host>prod-db</db.host> <!-- 覆盖settings中的localhost -->
<db.name>production</db.name>
</properties>
<repositories>
<repository>
<id>pom-repo</id>
<url>http://pom-repo</url>
</repository>
</repositories>
</profile>
</profiles>
激活命令:mvn clean install -Denv=prod
生效结果:
- 两个Profile都会激活
- 属性合并:db.host=prod-db (pom覆盖settings),db.port=3306 (settings),db.name=production (pom)
- 仓库合并:两个repository都会生效
3.2.5 命令行参数最高优先级
# 覆盖POM中的所有配置
mvn clean install -Djava.version=21 -DskipTests=true
# 覆盖settings.xml中的激活Profile
mvn clean install -P custom-profile
# 系统属性覆盖一切
mvn clean install -Duser.property=command-value
3.3 具体元素的优先级示例
示例1:依赖版本冲突解决
命令行指定版本 (最高) → 子POM直接依赖 → 父POM dependencyManagement → 传递依赖版本
# 命令行最高优先级
mvn package -Dspring.version=6.0.0
示例2:资源过滤优先级
<!-- 父POM -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering> <!-- 默认不过滤 -->
</resource>
</resources>
</build>
<!-- 子POM -->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering> <!-- 子POM覆盖为过滤 -->
</resource>
</resources>
</build>
示例3:插件配置合并
<!-- 父POM定义基础配置 -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<skipTests>false</skipTests>
<testFailureIgnore>false</testFailureIgnore>
</configuration>
</plugin>
<!-- 子POM扩展配置 -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<!-- 不指定version,继承父POM的3.0.0 -->
<configuration>
<includes>
<include>**/*Test.java</include> <!-- 新增配置 -->
</includes>
<!-- skipTests和testFailureIgnore继承父POM -->
</configuration>
</plugin>
<!-- 子POM覆盖配置 -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.0</version> <!-- 覆盖版本 -->
<configuration>
<skipTests>true</skipTests> <!-- 覆盖父POM配置 -->
</configuration>
</plugin>
四、 最佳实践
4.1 明确配置来源
- 基础配置放父POM
- 环境配置放Profile
- 项目特有配置放子POM
4.2 避免过度覆盖
<!-- 不推荐:完全覆盖父插件配置 -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<!-- 这里会完全替换父POM的configuration -->
</configuration>
</plugin>
<!-- 推荐:使用combine.children或combine.self属性 -->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration combine.children="append">
<!-- 追加配置,而不是替换 -->
<compilerArgs>
<arg>-Xlint:all</arg>
</compilerArgs>
</configuration>
</plugin>
4.3 合理使用属性
<!-- 使用属性提高灵活性 -->
<properties>
<spring.version>5.3.23</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
4.4 Profile设计原则
- 开发环境Profile默认激活
- 生产环境Profile通过命令行激活
- 不同Profile之间属性名保持一致
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)