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 实现属性的自动展开,并展示了如何在两种构建工具之间轻松迁移配置。