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

    • 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章 常见问题与最佳实践

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

properties

本章承接 parent 继承和聚合,深入讲解 Maven 的属性系统。properties 是 Maven POM 的"变量声明区",它让版本号、路径、编码等配置值从"硬编码"变为"可引用",是实现"一处修改、全局生效"的技术基础。


核心机制

官方明确将 properties 定位为变量系统。它的设计目的是消除重复、集中管理易变配置,让 POM 更具可维护性。

properties 标签的语法

在 POM 的 <properties> 区域,你可以定义任意名称的属性:

<properties>
    <java.version>17</java.version>
    <spring-boot.version>3.2.0</spring-boot.version>
    <mysql.version>8.0.33</mysql.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

命名规范:

  • 使用点号分隔的层级命名(如 java.version)
  • 避免与 Maven 内置属性冲突(如 project.version、project.basedir)
  • 自定义属性建议加前缀(如 feixiang.mysql.version)以避免命名空间污染

${property} 引用语法

定义后的属性可以在 POM 的任何支持表达式的地方用 ${} 引用:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>${spring-boot.version}</version>
</dependency>

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.11.0</version>
    <configuration>
        <source>${java.version}</source>
        <target>${java.version}</target>
    </configuration>
</plugin>

内置属性与自定义属性

Maven 提供了大量内置属性,无需在 <properties> 中定义即可使用:

内置属性含义示例
${project.version}当前 POM 的版本号2.0.0
${project.basedir}当前 POM 所在目录C:\workspace\employee-system
${project.build.directory}构建输出目录target
${env.HOME}环境变量/home/xiaocui
${java.home}JDK 安装目录C:\Program Files\Java\jdk-17

统一版本管理

properties 最常见的用途是统一依赖版本管理。在父 POM 中定义版本属性,子 POM 通过 ${} 引用,升级时只需修改父 POM 一处。

生活类比:公司通讯录

想象 properties 是公司通讯录:

  • 定义属性 = 把员工的手机号存进通讯录。java.version=17 就是"Java 版本这个员工的号码是 17"。
  • 引用属性 = 需要联系某人时,查通讯录而不是背号码。${java.version} 就是"帮我查一下 Java 版本员工的号码"。
  • 统一修改 = 员工换号了,只需在通讯录改一次。所有之前查过这个号码的人都会自动拿到新号。

如果没有通讯录(properties),每次打电话(写依赖版本)都要背号码(硬编码)。员工换号(版本升级)时,你得把所有记过旧号码的纸条(POM 文件)全部翻出来改一遍。


图示

上图展示了 properties 的核心价值:父 POM 集中定义"变量",子 POM 通过 ${} 引用"变量值"。当父 POM 中的 java.version 从 17 改为 21 时,所有引用它的子 POM 自动生效,无需逐个修改。


完整示例

场景

飞翔科技的 feixiang-parent 管理着 5 个子项目,每个子项目都依赖 Spring Boot 3.2.0 和 MySQL 8.0.33。CTO 大翔要求:升级 Spring Boot 到 3.3.0 时,只改一处配置,所有子项目自动生效。

操作前:硬编码版本

feixiang-parent/pom.xml(错误示范):

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.2.0</version>  <!-- 硬编码 -->
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.33</version>  <!-- 硬编码 -->
        </dependency>
    </dependencies>
</dependencyManagement>

问题:升级 Spring Boot 时,白歌需要检查所有子项目的 pom.xml,确认没有遗漏的硬编码版本。某个子项目如果偷偷写了自己的 <version>3.2.0</version>,升级时就会被遗漏,导致版本不一致。

操作步骤:用 properties 统一管理

第一步:在父 POM 中定义版本属性

<properties>
    <java.version>17</java.version>
    <spring-boot.version>3.2.0</spring-boot.version>
    <mysql.version>8.0.33</mysql.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>${mysql.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.11.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </pluginManagement>
</build>

第二步:子 POM 引用属性(或继承管理后的无版本依赖)

employee-system/pom.xml:

<project>
    <parent>
        <groupId>com.feixiang</groupId>
        <artifactId>feixiang-parent</artifactId>
        <version>2.0.0</version>
    </parent>

    <artifactId>employee-system</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 版本由父 POM 的 dependencyManagement 管理,底层通过 ${spring-boot.version} 解析 -->
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- source/target 通过 ${java.version} 继承 -->
            </plugin>
        </plugins>
    </build>
</project>

操作结果:版本升级前后对比

升级前(properties 定义):

<properties>
    <spring-boot.version>3.2.0</spring-boot.version>
</properties>

所有引用处的实际值:

位置生效版本
feixiang-parent 的 dependencyManagement3.2.0
employee-system 的 spring-boot-starter-web3.2.0
payroll-service 的 spring-boot-starter-web3.2.0
employee-web 的 spring-boot-starter-web3.2.0

升级后(只改父 POM 一处):

<properties>
    <spring-boot.version>3.3.0</spring-boot.version>
</properties>

所有引用处的实际值:

位置生效版本
feixiang-parent 的 dependencyManagement3.3.0
employee-system 的 spring-boot-starter-web3.3.0
payroll-service 的 spring-boot-starter-web3.3.0
employee-web 的 spring-boot-starter-web3.3.0

变化分析:

  • 白歌升级 Spring Boot 时,只需修改 feixiang-parent 中的 <spring-boot.version> 一行
  • 小崔在 employee-system 中无需任何修改,重新构建即自动使用 3.3.0
  • 李眉检查构建日志时,看到所有子项目下载的 Spring Boot 依赖版本一致,没有冲突

易错点与常见问题

误区一:properties 定义了,但引用处拼写错误

错误配置:

<properties>
    <mysql.version>8.0.33</mysql.version>
</properties>

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>${myql.version}</version>  <!-- 拼写错误!少了 t -->
</dependency>

后果:Maven 解析 ${myql.version} 时找不到定义,直接保留原字符串。构建时会报错:

[ERROR] 'dependencies.dependency.version' for com.mysql:mysql-connector-j:jar must be a valid version but is '${myql.version}'.

纠正:properties 的命名和引用必须完全一致。建议使用 IDE 的自动补全功能,或统一命名规范(如所有版本属性以 .version 结尾)。

误区二:在子 POM 中重复定义同名属性,以为会覆盖父 POM

配置(子 POM 中):

<properties>
    <java.version>21</java.version>
</properties>

后果:子 POM 中定义的 java.version 确实会覆盖父 POM 的值,但只在当前子 POM 生效。其他兄弟模块仍然使用父 POM 的值。这种"局部覆盖"会导致同一平台的不同服务使用不同的 Java 版本,增加运维复杂度。

纠正:如果确实需要某个子项目使用不同版本,应在属性名上做区分(如 payroll.java.version),而不是直接覆盖通用属性。平台级属性应在父 POM 统一管理。

误区三:把敏感信息放进 properties

错误配置:

<properties>
    <jdbc.password>MySecret123</jdbc.password>
</properties>

后果:密码被硬编码在 pom.xml 中,提交到 Git 后所有团队成员都能看到。更危险的是,如果项目开源或打包发布,密码会随 POM 一起泄露。

纠正:敏感信息(密码、API Key、Token)绝对不应该放在 pom.xml 的 properties 中。应使用环境变量、外部配置文件或 Maven 的 settings.xml 中的 <servers> 配置。


小结

properties 是 Maven POM 的变量系统,通过 <properties> 定义值、通过 ${} 引用值,实现了配置的集中管理和灵活复用。在父 POM 中用 properties 统一管理依赖版本、Java 版本、编码等关键参数,可以让版本升级从"全项目搜索替换"变为"修改一行、全局生效"。注意避免拼写错误、谨慎使用局部覆盖、绝不存放敏感信息。

本章与全局的关系:本章讲解了 POM 内部的变量机制。下一节将讲解 BOM(Bill of Materials),它是 properties + dependencyManagement 的高级组合形式,用于管理更复杂的第三方生态版本。

上一页
BOM