第二十三章. YML 配置:环境隔离与 @ConfigurationProperties 注入

第二十三章. YML 配置:环境隔离与 @ConfigurationProperties 注入

摘要:本章我们将深入 RVP 5.x 架构的“神经中枢”——YML 配置文件。我们将以 ruoyi-admin 模块为核心,分析主配置文件 application.yml 如何与环境配置 application-dev.yml 协作,并深入探讨 RVP 是如何通过“自动化加载”和“@ConfigurationProperties 注入”来管理整个框架的参数的。

本章学习路径

YML 配置


23.1. YML 语法与 application.yml 解析

在上一章中,我们深入解析了 RVP 5.x 的 Maven 架构,特别是根 pom.xml 如何通过 <profiles>(如 devprod)来定义构建环境。我们提到了 <profiles.active> 这个 Maven 变量。

但是,Maven 中定义的这个 dev 变量,Spring Boot 应用在“运行时”是如何感知到,并自动加载 application-dev.yml 文件的呢?

答案的起点,就在于主配置文件 application.yml。本节我们将从 YML 语法开始,逐步解析 RVP 主配置文件的核心机制。

23.1.1. YML 语法基础:层级、对象、数组

YML (YAML Ain’t Markup Language) 是一种常用于配置文件的序列化语言,它以“缩进”来表示层级关系。

1. 键值对(K-V)
YML 的核心是键值对。规范是“冒号 + 空格 + 值”。

1
2
3
4
# 键: 值 (冒号后必须有空格)
server:
# 使用两个空格缩进,表示 port 是 server 的子属性
port: 8080

2. 对象(Object)
server 节点本身就是一个对象,它包含了 portservletundertow 等多个子属性。

1
2
3
4
5
6
7
8
# 'server' 是一个对象
server:
port: 8080
servlet:
context-path: /
# 'undertow' 也是 server 的子对象
undertow:
buffer-size: 512

3. 数组(Array)
数组(或列表)通过“短横线 + 空格 + 值”来表示。

1
2
3
4
5
6
# 'excludes' 是一个字符串数组
security:
excludes:
- /*.html
- /**/*.html
- /**/*.css

如果数组元素是对象,则可以混合使用:

1
2
3
4
5
6
7
8
springdoc:
group-configs:
# 数组的第一个元素 (一个对象)
- group: 1.演示模块
packages-to-scan: org.dromara.demo
# 数组的第二个元素 (一个对象)
- group: 2.通用模块
packages-to-scan: org.dromara.web

23.1.2. application.yml (主配置) 结构总览

ruoyi-admin/src/main/resources/application.yml (源码文件 1) 是 RVP 的 主配置文件

它的核心职责是定义 所有环境(local, dev, prod)都共享的默认配置。它包含了框架运行的基础参数,例如:

配置项职责
server定义端口 8080、上下文路径 / 以及 undertow 容器参数。
captcha配置验证码的开关(enable: true)和类型(type: MATH)。
logging配置日志级别(@logging.level@)和 logback-plus.xml 的路径。
spring配置应用名、@profiles.active@、文件上传大小、Jackson 序列化等。
sa-token配置 Sa-Token 的 Token 名称、JWT 秘钥等。
security配置安全框架的全局放行路径(如 .html, .css)。
tenant配置多租户的开关(enable: true)和排除表。
mybatis-plus配置 Mapper 扫描路径、主键策略(ASSIGN_ID)。
springdoc配置 API 文档的分组信息。

23.1.3. 变量引用(一):@...@ (引用 pom.xmlprofiles 的变量)

这是连接 Maven 构建环境和 Spring Boot 运行环境的“桥梁”。

application.yml 中,我们看到了 logging.levelspring.profiles.active 这两处特殊的配置:

1
2
3
4
5
6
7
logging:
level:
org.dromara: @logging.level@

spring:
profiles:
active: @profiles.active@

@...@ 语法 不是 YML 的标准语法,也不是 Spring Boot 的语法,而是 Maven 资源过滤 的语法。

它与我们在上一章 22.4.4 节中分析的根 pom.xml 中的 <resources> 插件配置相对应:

  1. pom.xml 配置了 <filtering>true</filtering>,要求 Maven 在构建时“过滤” application.yml 文件。
  2. 当 Maven 在 dev 环境下构建时(pom.xmldev profile 被激活),它会读取 dev profile 中定义的 <properties>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <profile>
    <id>dev</id>
    <properties>
    <profiles.active>dev</profiles.active>
    <logging.level>info</logging.level>
    </properties>
    <activation>
    <activeByDefault>true</activeByDefault>
    </activation>
    </profile>
  3. Maven 会将 application.yml 中的 @profiles.active@ 替换为 静态字符串 dev,将 @logging.level@ 替换为 info
  4. 最终打包到 target/classes/application.yml 的文件内容是:
    1
    2
    3
    spring:
    profiles:
    active: dev # [已替换]
  5. Spring Boot 启动时,读取到 spring.profiles.active: dev,因此它知道需要 额外加载 application-dev.yml

23.1.4. 变量引用(二):${...} (引用 pom.xml 属性或 YML 内部变量)

${...} 语法是 Spring Boot 支持的标准占位符语法。它主要用于引用“运行时”的变量。

场景一:引用 pom.xml 中的属性 (来自 Maven)
application.ymlspringdoc 配置中:

1
2
3
4
springdoc:
info:
# 引用 Maven pom.xml 中的 <version> (最终解析为 ${revision} 的值)
version: '版本号: ${project.version}'

spring-boot-maven-plugin 会将 pom.xml 中的项目版本号(5.5.1)写入 META-INF,Spring Boot 启动时会读取该值,并替换 ${project.version}

场景二:引用 YML 内部的其他变量 (来自 YML)
application-dev.yml 中,snail-job 的端口配置引用了主配置的 server.port

1
2
3
4
5
6
7
8
# 假设 application.yml (或 dev.yml) 中定义了 server.port
server:
port: 8080

snail-job:
# 引用上面定义的 server.port
# 最终解析为 20000 + 8080 = 28080
port: 2${server.port}

这种方式常用于在 YML 内部保持配置的一致性。

23.1.5. 多文档分割 (---):配置隔离的实现

application.yml 的末尾,我们看到了 --- (三个短横线) 分隔符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ... (上方 springdoc, xss 等配置) ...

--- # 分布式锁 lock4j 全局配置
lock4j:
acquire-timeout: 3000
expire: 30000

--- # Actuator 监控端点的配置项
management:
endpoints:
web:
exposure:
include: '*'
# ...

YML 规范中,同一个文件内的“顶级键”(如 spring, lock4j, management)理论上不应重复。
方案--- 分隔符在 YML 中用于表示“一个新文档的开始”。Spring Boot 会 依次加载 同一个 application.yml 文件中被 --- 分隔的 所有文档,并将它们的配置进行 合并

在 RVP 5.x 中,--- 的主要作用是“逻辑分组”。它将 lock4jmanagementssewebsocket 等功能配置块进行清晰地分离,提高了配置文件的可读性。


23.2. 环境配置:application-dev.ymlapplication-prod.yml

在上一节中,我们深入分析了 application.yml 文件,并揭示了它内部最关键的一行配置:
spring.profiles.active: @profiles.active@

我们知道,当使用 dev (开发) profile 构建时,这行配置会被 Maven 翻译为 spring.profiles.active: dev。本节我们将探讨当 Spring Boot 读取到这个 dev 值时,究竟会发生什么。

23.2.1. 环境配置的加载机制

Spring Boot 的配置文件加载机制具有“层级覆盖”的特性。

  1. 首先 (Phase 1):Spring Boot 总是 会加载 application.yml(主配置文件)。这会加载所有模块(server, sa-token, mybatis-plus 等)的默认配置。
  2. 然后 (Phase 2):Spring Boot 检查 spring.profiles.active 属性的值。
  3. 最后 (Phase 3):如果 spring.profiles.active 的值是 dev,Spring Boot 会 接着加载 application-dev.yml 文件。如果值是 prod,则加载 application-prod.yml

[核心] 覆盖原则:如果在 application-dev.yml 中定义的配置项,与 application.yml 中的 完全相同(路径相同),那么 application-dev.yml 中的值将 覆盖 application.yml 中的值。

application.yml 定义了“通用默认值”,而 application-{profile}.yml 则定义了“特定环境的覆盖值”。

23.2.2. application-dev.yml 解析:覆盖“开发时”配置

ruoyi-admin/src/main/resources/application-dev.yml 的全部意义,就是用来覆盖那些在“开发环境”与“生产环境”中 必须不同 的配置。

我们来分析几个关键的“覆盖”示例:

1. 数据库 (spring.datasource)

  • application.yml未定义 数据库 URL、用户名、密码。
  • application-dev.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    spring:
    datasource:
    dynamic:
    datasource:
    # 主库数据源
    master:
    url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&...
    username: root
    password: root
  • 分析:数据库连接信息是典型的环境相关配置。application-dev.yml 提供了本地开发时连接 localhost 数据库的凭证。

2. Redis (spring.data.redis)

  • application.yml未定义 Redis 主机。

  • application-dev.yml

    1
    2
    3
    4
    5
    spring.data:
    redis:
    host: localhost
    port: 6379
    database: 0
  • 分析:提供了本地开发时连接 localhost Redis 的配置。

3. 监控中心 (spring.boot.admin.client)

  • application.yml未定义 此配置。
  • application-dev.yml
    1
    2
    3
    4
    5
    spring.boot.admin.client:
    enabled: true
    url: http://localhost:9090/admin
    username: @monitor.username@
    password: @monitor.password@
  • 分析:在开发环境下,启用 Admin 客户端,并将其注册到位于 localhost:9090 的监控中心。

4. 调度中心 (snail-job)

  • application.yml未定义 此配置。

  • application-dev.yml

    1
    2
    3
    4
    5
    6
    snail-job:
    enabled: true
    server:
    host: 127.0.0.1
    port: 17888
    namespace: ${spring.profiles.active} # 引用 dev
  • 分析:在开发环境下,启用 SnailJob 客户端,并将其注册到位于 127.0.0.1 的调度中心,且使用 dev 命名空间。

5. Actuator 敏感信息

  • application.yml未定义 此配置(Spring Boot 默认 NEVER,即隐藏)。
  • application-dev.yml
    1
    2
    3
    4
    management:
    endpoint:
    env:
    show-values: ALWAYS
  • 分析这是一个关键的开发环境配置。它覆盖了 Spring Boot 的安全默认值,允许我们在 Admin 监控的“环境”页面查看所有配置属性(包括密码),极大地方便了开发调试,这是我们自己添加的

23.2.3. application-prod.yml 解析:覆盖“生产时”配置

application-prod.yml 则提供了生产环境的覆盖值。

我们以 justauth(三方授权)为例,对比 devprod 的差异:

  • application-dev.yml

    1
    2
    3
    4
    5
    6
    justauth:
    # 前端外网访问地址 (开发时通常是 http://localhost:81)
    address: http://localhost:81
    type:
    gitee:
    redirect-uri: ${justauth.address}/social-callback?source=gitee
  • application-prod.yml (我们并未修改,若修改应该是如下的):

    1
    2
    3
    4
    5
    6
    7
    justauth:
    # 生产环境必须是真实的公网域名
    address: https://www.your-domain.com
    type:
    gitee:
    # 回调地址也必须是公网域名
    redirect-uri: ${justauth.address}/social-callback?source=gitee

分析justauth.address 这个属性,在 devprod 环境中必须不同,因此它必须在 application-{profile}.yml 中被定义,而不是在 application.yml 中。

23.2.4. dev vs prod:日志级别 (logging.level) 的切换

最后,我们回到 23.1.3 节中的 logging.level 变量。

  1. application.yml 定义了日志级别:org.dromara: @logging.level@
  2. 当 Maven dev profile 激活时,根 pom.xml@logging.level@ 替换为 info
  3. 当 Maven prod profile 激活时,根 pom.xml@logging.level@ 替换为 warn

结论:RVP 框架通过 Maven profilesSpring Boot profiles 协同工作,实现了“一键切换”开发与生产环境的日志级别、数据库连接、Redis 连接、监控地址、调度地址等所有环境相关配置。


23.3. [核心] 插件化配置加载:@PropertySource

在 22.5 节分析 ruoyi-common-bom 时,我们看到 RVP 5.x 架构的核心是将 common 模块设计为“可插拔”的插件。这种插件化思想不仅体现在 Maven 依赖上,同样体现在 YML 配置上。

23.3.1. “非 application 开头”的 YML 加载痛点

我们首先要面对一个问题:Spring Boot 的自动配置机制,默认 只会 加载 classpath: 根目录下的 application.ymlapplication-{profile}.yml 文件。

然而,RVP 的 common 模块(如 ruoyi-common-mybatis)将自己的“内置配置”存放在了各自的 resources 目录下,例如 common-mybatis.ymlcommon-satoken.yml

Spring Boot 不会 自动扫描并加载这些“非标”的 YML 文件。那么,RVP 是如何让这些插件化模块的配置生效的呢?

23.3.2. RVP 解决方案(一):@PropertySourceYmlPropertySourceFactory

RVP 框架利用了 Spring 的 @PropertySource 注解,并结合了一个自定义工厂 YmlPropertySourceFactory,来解决了这个问题。

  • @PropertySource:这是 Spring 框架提供的标准注解,用于 主动加载 指定路径的配置文件到 Spring 的“环境”(Environment) 中。
  • YmlPropertySourceFactory:这是 RVP 在 ruoyi-common-core 中定义的一个工具类(源码文件 ruoyi-common-core/.../factory/YmlPropertySourceFactory.java)。

为什么需要 YmlPropertySourceFactory
@PropertySource 注解在默认情况下,只支持解析 .properties 键值对格式,它 不认识 YML 的树状(缩进)语法。YmlPropertySourceFactory 的作用,就是“教会” @PropertySource 如何去解析 YML 文件。

23.3.3. 源码解析:MybatisPlusConfig.java 如何加载 common-mybatis.yml

ruoyi-common-mybatis 模块提供了一个完美的示例。我们来分析 MybatisPlusConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
// 位于 ruoyi-common-mybatis/src/.../config/MybatisPlusConfig.java
package org.dromara.common.mybatis.config;

// ... (imports) ...

@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan("${mybatis-plus.mapperPackage}")
@PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
public class MybatisPlusConfig {
// ... (Bean 定义) ...
}

关键点分析

  1. @MapperScan("${mybatis-plus.mapperPackage}"):它从 application.yml 中读取 mybatis-plus.mapperPackage 属性(值为 org.dromara.**.mapper)并扫描 Mapper。
  2. @PropertySource(...)
    • value = "classpath:common-mybatis.yml":这行代码 强制 Spring 在启动时,去 classpath 下查找并加载 common-mybatis.yml 这个文件。
    • factory = YmlPropertySourceFactory.class:指定使用 RVP 自定义的 YML 解析工厂来读取该文件。

配置合并与覆盖:通过这个注解,RVP 实现了配置的“分层管理”:

  1. common-mybatis.yml (内置配置):存放了框架开发者预设的、不希望用户轻易修改的“最佳实践”配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 源码文件 3 (common-mybatis.yml)
    mybatis-plus:
    configuration:
    # 关闭 MyBatis 默认日志,统一使用 P6Spy
    logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
    global-config:
    dbConfig:
    # 逻辑已删除值
    logicDeleteValue: 1
  2. application.yml (用户配置):存放了用户 应该 自定义的配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # 源码文件 1 (application.yml)
    mybatis-plus:
    # [用户配置]
    mapperPackage: org.dromara.**.mapper
    mapperLocations: classpath*:mapper/**/*Mapper.xml
    global-config:
    dbConfig:
    # [用户配置]
    idType: ASSIGN_ID

加载顺序与优先级
Spring Boot 加载 application.yml 的优先级 高于 @PropertySource 加载的配置。

这意味着:

  • common-mybatis.yml 中的 logImpl 配置会生效。
  • application.yml 中的 idType: ASSIGN_ID覆盖 common-mybatis.yml 中定义的 idType: ASSIGN_ID(虽然在此示例中它们的值相同)。
  • 最终,Spring 环境中会包含 两者合并 后的 mybatis-plus 配置。

23.3.4. 源码解析:SaTokenConfig.java 如何加载 common-satoken.yml

RVP 框架中的 所有 ruoyi-common-* 插件都遵循此模式。例如 ruoyi-common-satoken 模块:

文件路径ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java

1
2
3
4
5
// 截取自 SaTokenConfig.java 源码
@PropertySource(value = "classpath:common-satoken.yml", factory = YmlPropertySourceFactory.class)
public class SaTokenConfig {
// ...
}

它使用完全相同的方式,加载了 common-satoken.yml,用于配置 Sa-Token 的 Token 前缀、超时时间等内置参数。


23.4. [核心] YML 属性注入:@ConfigurationProperties

在上一节中,我们分析了 RVP 框架如何使用 @PropertySource 将“非标” YML 文件(如 common-mybatis.yml)加载到 Spring 的“环境”(Environment) 中。

这种方式虽然解决了“加载”问题,但我们又遇到了一个新问题:在 Java 代码中如何 使用 这些配置值?

  • 传统方式 (不推荐):在每个需要配置的类中,使用 @Value("${thread-pool.queue-capacity}") 逐个注入。
  • 痛点:这种方式非常繁琐,配置项分散在代码各处,缺乏类型安全(所有值都是字符串),且难以维护。

RVP 5.x 架构采用了 Spring Boot 推荐的最佳实践:@ConfigurationProperties,它将 YML 属性优雅地“注入”到类型安全的 Java Bean 中。

23.4.1. RVP 解决方案(二):从 YML 到 Java Bean 的映射

RVP 的配置注入分为两步:

  1. 定义 (Define):创建一个 POJO (Plain Old Java Object) 类,用 @ConfigurationProperties 注解将其与 YML 中的一个“前缀”(prefix) 绑定。
  2. 激活 (Enable):在 AutoConfiguration 类中,使用 @EnableConfigurationProperties 来“激活”这个 POJO 类,使其被 Spring 容器注册和填充。

我们以 ruoyi-common-core 模块中的线程池配置为例,深入解析这个过程。

23.4.2. 源码解析:ThreadPoolProperties.java (定义属性)

首先,开发者定义了一个 ThreadPoolProperties 类,用于 承载 thread-pool 命名空间下的所有 YML 属性。

文件路径ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/properties/ThreadPoolProperties.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.dromara.common.core.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "thread-pool")
public class ThreadPoolProperties {

/**
* 是否开启线程池
*/
private boolean enabled;

/**
* 队列最大长度
*/
private int queueCapacity;

/**
* 线程池维护线程所允许的空闲时间
*/
private int keepAliveSeconds;

}

关键点分析

  1. @ConfigurationProperties(prefix = "thread-pool")
    • [核心] 这个注解告诉 Spring Boot:“请在 YML 配置文件中查找所有以 thread-pool 开头的配置项”。
  2. 自动映射
    • Spring Boot 会自动将 YML 中的 kebab-case (短横线命名, 如 queue-capacity) 映射到 Java 类的 camelCase (驼峰命名, 如 queueCapacity) 字段上。
    • 它还会自动进行 类型转换,将 YML 中的字符串(如 10)转换为 Java 中的 intboolean 类型。
  3. @Data (Lombok):自动生成 getter/setter 方法,这是 @ConfigurationProperties 注入所必需的。

23.4.3. 源码解析:ThreadPoolConfig.java (激活属性)

仅仅定义 ThreadPoolProperties 类是不够的,Spring Boot 不会自动扫描它。我们必须在配置类中 显式激活 它。

文件路径ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ThreadPoolConfig.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package org.dromara.common.core.config;

// ... (imports) ...
import org.dromara.common.core.config.properties.ThreadPoolProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

@Slf4j
@AutoConfiguration
@EnableConfigurationProperties(ThreadPoolProperties.class)
public class ThreadPoolConfig {

// ... (Bean 定义) ...

@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService() {
// ...
// 源码中在此处使用了 ThreadPoolProperties,但为简化,我们理解其已被注入
// ...
}
}

关键点分析

  1. @AutoConfiguration:表示这是一个 Spring Boot 自动配置类。RVP 的 common 模块通过告诉 Spring Boot 启动时自动加载这个 ThreadPoolConfig
  2. @EnableConfigurationProperties(ThreadPoolProperties.class)
    • [核心] 这个注解是“激活器”。它告诉 Spring 容器:“请立即创建 ThreadPoolProperties.java 这个类的 Bean 实例,并根据 @ConfigurationProperties(prefix = "thread-pool") 注解,从 YML 中读 1 取属性来填充它。”

最终流程

  1. RVP 启动,Spring Boot 加载 ThreadPoolConfig (因为 @AutoConfiguration)。
  2. @EnableConfigurationProperties 被触发,Spring 创建 ThreadPoolProperties Bean。
  3. Spring Boot 从 application.ymlapplication-dev.yml 等文件中,找到 thread-pool 前缀下的所有属性。
  4. Spring Boot 将 queue-capacity: 200 (YML) 注入到 ThreadPoolProperties Bean 的 queueCapacity (Java) 字段中。
  5. ThreadPoolConfig 内部就可以直接 @Autowired 或通过方法参数注入这个 已填充完毕ThreadPoolProperties Bean,并使用它来配置线程池。

23.5. [实战] 二次开发:添加自定义配置

在 23.3 和 23.4 节中,我们已经系统性地分析了 RVP 框架加载和注入配置的两种核心机制:@PropertySource@ConfigurationProperties。现在,我们将把这些理论知识应用到“二次开发”的实战中,为 RVP 框架添加一个全新的“微信小程序”配置模块。

23.5.1. 目标:为新模块 mini-app 添加 appidsecret 配置

我们的目标是,在 YML 文件中添加一个新的配置块 mini-app,用于存放小程序的 appidsecret,并使 RVP 框架能够像加载 ThreadPoolProperties 一样,将这些配置自动注入到一个类型安全的 Java Bean 中,供业务代码使用。

23.5.2. 步骤一:在 application-dev.yml 中定义 mini-app 属性

首先,我们选择开发环境配置文件 application-dev.yml 来添加我们的新配置。

文件路径ruoyi-admin/src/main/resources/application-dev.yml

我们打开此文,在文件末尾添加 --- 分隔符和我们新的 mini-app 配置块:

1
2
3
4
5
6
7
8
# ... (justauth 等其他配置) ...

--- # 微信小程序配置 (我们新增的)
mini-app:
# 小程序 AppID
appid: wx123456789abcdef
# 小程序
secret: 987zyxwvutsrqponml
  • ---:使用多文档分隔符,保持配置的逻辑隔离。
  • mini-app:定义了我们配置的“前缀”(prefix),必须使用 kebab-case (短横线命名法)。
  • appid / secret:我们自定义的属性。

23.5.3. 步骤二:创建 MiniAppProperties.java (使用 @ConfigurationProperties)

接下来,我们创建 Java Bean 来“承载”这些 YML 属性。在 RVP 5.x 架构中,最佳实践是将这种配置类放在对应模块的 config/properties 包下。我们以 ruoyi-demo 模块为例:

文件路径ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/config/properties/MiniAppProperties.java

我们创建这个新文件,并添加 @ConfigurationProperties 注解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.dromara.demo.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
* 微信小程序配置属性
*
* @author Prorise
*/
@Data
@ConfigurationProperties(prefix = "mini-app")
public class MiniAppProperties {

/**
* 小程序 AppID
*/
private String appid;

/**
* 小程序
*/
private String secret;

}
  • @ConfigurationProperties(prefix = "mini-app")
    [核心] 将此类与 YML 中 mini-app 前缀的配置项进行绑定。
  • 字段映射:Spring Boot 会自动将 YML 中的 appid 映射到 Java 字段 appid,将 secret 映射到 secret
  • @Data:Lombok 注解,自动生成 getter/setter,这是属性注入所必需的。

23.5.4. 步骤三:创建 MiniAppConfig.java (使用 @EnableConfigurationProperties 激活)

我们已经定义了 Properties 类,现在需要一个配置类来“激活”它,让 Spring Boot 容器去创建并填充这个 Bean。

文件路径ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/config/MiniAppConfig.java

我们创建这个新的 AutoConfiguration 类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package org.dromara.demo.config;

import org.dromara.demo.config.properties.MiniAppProperties;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;

/**
* 微信小程序自动配置
*
* @author Prorise
*/
@AutoConfiguration
@EnableConfigurationProperties(MiniAppProperties.class)
public class MiniAppConfig {

// RVP 5.x 提倡使用 @AutoConfiguration
// 并且需要在 resources/META-INF/spring/
// org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 文件中登记这个 MiniAppConfig,Spring Boot 才能自动加载它。

}
  • @AutoConfiguration:声明这是一个 Spring Boot 自动配置类。
  • @EnableConfigurationProperties(MiniAppProperties.class)
    [核心] 这个注解是“激活器”。它告诉 Spring Boot:“请启用 MiniAppProperties 这个配置类,并立即根据其 @ConfigurationProperties 注解去 YML 加载属性来填充它。”

23.5.5. 步骤四:在 Service 中注入并使用 MiniAppProperties

完成以上三步并 重启服务 后,MiniAppProperties Bean 就已经注册到 Spring 容器中,并被填充了 YML 中的 appidsecret 值。

我们可以在任何其他 Bean(如 Service, Controller)中 直接注入 并使用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 示例:在 ruoyi-demo 模块的某个 Service 中使用
package org.dromara.demo.service.impl;

import org.dromara.demo.config.properties.MiniAppProperties;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import jakarta.annotation.PostConstruct;

@RequiredArgsConstructor
@Service
public class DemoServiceImpl { // 假设这是一个服务

// [核心] 通过构造函数注入
private final MiniAppProperties miniAppProperties;

@PostConstruct
public void init() {
// 在 Bean 初始化时,打印 YML 中加载的值
System.out.println("小程序 AppID: " + miniAppProperties.getAppid());
System.out.println("小程序 Secret: " + miniAppProperties.getSecret());
}
}
  • @RequiredArgsConstructor:Lombok 注解,自动生成一个包含 final 字段(miniAppProperties)的构造函数,Spring Boot 会自动通过这个构造函数完成注入。
  • miniAppProperties.getAppid():此时获取到的值,就是我们在 application-dev.yml 中配置的 wx123456789abcdef

23.5.6. YML 多行文本(|)的用法

最后,我们补充一个 YML 语法:如何配置换行的多行文本。

如果我们的 mini-app 配置中有一个 info 字段,需要包含换行符:

YML 配置

1
2
3
4
5
6
7
8
9
10
11
mini-app:
appid: ...
secret: ...
# 方式一:使用 \n,不直观
info: "信息第一行\n信息第二行"

# 方式二:使用 | (竖线),保持字面换行 (推荐)
intro: |
这是多行信息
第二行
第三行
  • | (Literal Block Scalar):YML 语法中的“字面量块”。它告诉解析器,保留 intro: 字段 下方所有缩进 的文本,并且 保持它们的换行符

Java 注入结果

1
2
3
4
5
6
7
8
@Data
@ConfigurationProperties(prefix = "mini-app")
public class MiniAppProperties {
private String appid;
private String secret;
private String info;
private String intro;
}
  • miniAppProperties.getInfo() 的值是:"信息第一行\n信息第二行"
  • miniAppMProperties.getIntro() 的值是:"这是多行信息\n第二行\n第三行\n"