Spring Boot 中的自动属性展开

更新于 2025-12-30

Roman Seleznov 2017-08-31

1. 概述

在本文中,我们将探讨 Spring 通过 Maven 和 Gradle 构建工具所提供的属性展开(Property Expansion)机制。

2. Maven

2.1. 默认配置

对于使用 spring-boot-starter-parent 的 Maven 项目,无需额外配置即可使用属性展开功能:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.5</version>
</parent>

现在,我们可以使用 @...@ 占位符来展开项目中的属性。以下是一个示例,展示如何将 Maven 中的项目版本保存到配置文件中:

expanded.project.version=@project.version@
expanded.project.property=@custom.property@

这些属性展开仅适用于符合以下命名模式的配置文件:

  • **/application*.yml
  • **/application*.yaml
  • **/application*.properties

2.2. 手动配置

如果项目未使用 spring-boot-starter-parent 作为父 POM,则需要手动配置资源过滤和属性展开。需在 pom.xml<build> 节点中添加如下 <resources> 配置:

<resources>
    <resource>
        <directory>${basedir}/src/main/resources</directory>
        <filtering>true</filtering>
        <includes>
            <include>**/application*.yml</include>
            <include>**/application*.yaml</include>
            <include>**/application*.properties</include>
        </includes>
    </resource>
</resources>

同时,在 <plugins> 中配置 maven-resources-plugin 插件:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.7</version>
    <configuration>
        <delimiters>
            <delimiter>@</delimiter>
        </delimiters>
        <useDefaultDelimiters>false</useDefaultDelimiters>
    </configuration>
</plugin>

如果希望使用标准的 ${variable.name} 类型占位符,则需将 useDefaultDelimiters 设置为 true,此时 application.properties 文件内容如下所示:

expanded.project.version=${project.version}
expanded.project.property=${custom.property}

3. Gradle

3.1. 标准 Gradle 解决方案

Spring Boot 官方文档中提供的 Gradle 解决方案并不完全兼容 Maven 的属性过滤与展开机制。

要启用属性展开功能,需在 build.gradle 中添加以下代码:

processResources {
    expand(project.properties)
}

但该方案存在以下限制,与 Maven 默认配置有所不同:

  • 不支持包含点号(.)的属性名(例如 user.name),因为 Gradle 将点号视为对象属性分隔符;
  • 会对所有资源文件进行过滤,而不仅限于特定的配置文件;
  • 使用默认的 ${...} 占位符,这会与 Spring 自身的标准占位符产生冲突。

3.2. 与 Maven 兼容的解决方案

为了复现 Maven 的标准行为,并使用 @...@ 风格的占位符,我们需要在 build.gradle 中添加如下代码:

import org.apache.tools.ant.filters.ReplaceTokens

processResources {
    with copySpec {
        from 'src/main/resources'
        include '**/application*.yml'
        include '**/application*.yaml'
        include '**/application*.properties'
        project.properties.findAll().each { prop ->
            if (prop.value != null) {
                filter(ReplaceTokens, tokens: [(prop.key): prop.value])
                filter(ReplaceTokens, tokens: [('project.' + prop.key): prop.value])
            }
        }
    }
}

此配置将解析所有项目属性。虽然在 build.gradle 中仍无法直接定义带点号的属性(如 user.name),但我们现在可以使用 gradle.properties 文件以标准 Java 属性格式定义属性,且该方式支持带点号的属性名(例如 database.url)。

此外,该构建脚本仅过滤项目配置文件,而非全部资源文件,因此与 Maven 方案完全兼容

4. 结论

在本篇简明教程中,我们了解了如何在 Spring Boot 项目中通过 Maven 和 Gradle 实现属性的自动展开,并展示了如何在两种构建工具之间轻松迁移配置。