第十三章. 系统管理(七):参数设置(无需重启的“热配置”中心)

第十三章. 系统管理(七):参数设置(无需重启的“热配置”中心)

摘要:本章我们将学习一个极其有用的模块——参数设置。在开发中,有些配置(如 application.yml)一旦写死,修改后必须重启服务。本章的核心就是教大家如何利用“参数设置”模块,实现 无需重启服务,动态修改并“热加载”配置的开发技巧。


本章学习路径

我们将从“为什么需要它”这一核心出发点,来深入理解参数设置的应用价值:

参数设置


13.1. [核心] 参数设置的价值:对比 application.yml

在开始本章前,我们必须回答一个问题:“我为什么需要‘参数设置’?我把配置写在 application.yml 文件里,不是更简单吗?”

这是一个直击灵魂的问题。如果你是 Spring Boot 开发者,你一定习惯了在 yml 文件中管理一切。但 yml 有一个“致命”的局限。

13.1.1. 静态配置(yml)的局限:修改即重启

application.yml (或 .properties) 是一种 静态配置

“静态”意味着,它在 服务启动时 被一次性加载到内存中。

  • 场景:假设你把“用户初始密码”配置在了 yml 文件中:user.init-password: 123456
  • 痛点:某天,公司安全策略升级,要求初始密码改成 abc@123。你兴高采烈地修改了 yml 文件。
  • 然后呢?
  • 配置不会生效!
  • 你必须 关闭 正在运行的服务,重新打包,然后 重启 服务。

在开发环境中,这只是几秒钟的事。但在 生产环境 中,“重启服务”是一个高风险、高成本的 SOP(标准作业流程),它会导致服务瞬间中断。

13.1.2. “动态配置”的价值:热加载与业务解耦

“参数设置”模块(sys_config 表)就是为了解决这个痛点而生的,它是一种 动态配置

  • 场景:我们把“用户初始密码”配置在“参数设置”模块中。
  • 修改:当安全策略变更时,管理员只需登录后台,修改 sys.user.initPassword 这条参数的“参数键值”为 abc@123,点击“保存”。
  • 然后呢?
  • 立刻生效!
  • 无需重启!

这就是 “热加载”“热配置”

RVP 的后端代码在需要“初始密码”时,不是 去读 yml 文件,而是去 实时(或读缓存)获取 sys_config 表中的数据。

核心思维

application.yml:放“死”的配置(如数据库地址、Redis 端口),这些配置在服务生命周期内 绝不会变

参数设置 :放“活”的配置(如初始密码、功能开关、第三方 IP),这些是 业务运营中可能需要动态调整**的参数。


13.2. [重点] 核心配置与缓存机制

我们点击 系统管理 -> 参数设置,来看一下它的构造。

这个界面本质上是一个 Key-Value 存储。

image-20251111214053050

13.2.1. “参数键名”(Config Key)的规范与应用

“参数键名”(config_key)是 给程序看的“变量名”。它是我们后端代码从数据库中获取配置的唯一“抓手”。

  • 例如sys.user.initPassword
  • 规范:RVP 推荐使用“点分式”命名法。系统自带的以 sys. 开头,我们自己开发的业务参数,推荐以 user. 或其他业务模块名(如 oms.)开头,便于区分。
  • 应用:在后端代码中,RVP 封装了工具类,我们只需一行代码(如 ConfigUtils.getConfigKey("sys.user.initPassword"))就能获取到它对应的“值”。

13.2.2. “参数键值”(Config Value)

“参数键值”(config_value)就是我们要存储的“内容”,它在数据库中通常以字符串形式存储。

  • 例如123456

13.2.3. 缓存机制解析:何时需要“刷新缓存”

我们注意到右上角有一个“刷新缓存”按钮。这又引出了一个性能问题:

如果系统每次需要“初始密码”时,都去查询一次数据库,当 1000 个用户同时注册时,就会产生 1000 次对 sys_config 表的查询,这是不可接受的。

因此,RVP 的标准做法是:

  1. 系统启动时,将 sys_config 表中的 所有参数 加载到 缓存 中(如 Redis 或内存)。
  2. 当代码需要 sys.user.initPassword 时,它 优先从缓存中读取,速度极快。
  3. 问题来了:当我们通过“修改”按钮,把密码从 123456 改成 abc@123 时,发生了什么?
    • RVP 同时做了两件事:1) 更新数据库。2) 自动 刷新缓存中 这一个 key 对应的值。
    • 所以,在 99% 的情况下,我们通过 UI 正常修改,不需要 手动点“刷新缓存”。

那么,“刷新缓存”是干嘛用的?

它是一个“手动纠错”的保险按钮。唯一的应用场景是:你(作为开发者)绕过了 UI 界面,直接用 SQL 语句或数据库工具(如 Navicat)手动修改了 sys_config

在这种情况下,RVP 框架 无法感知 到这个“非法”操作,缓存 没有被更新。此时,你才需要回来“啪”地按一下“刷新缓存”,强制 RVP 重新从数据库加载所有配置到缓存中。


13.3. [进阶] JSON 键值的应用

“参数键值”只能存 123456 这样的简单字符串吗?不,它可以更强大。

13.3.1. 案例:使用 JSON 键值存储复杂对象

假设我们的业务需要一组“学生信息”作为配置。

我们完全可以点击“新增”,然后这样填写:

  • 参数名称学生配置信息

  • 参数键名user.student.info

  • 参数键值:(这里是重点,我们填入一个 JSON 字符串)

    1
    2
    3
    4
    5
    {
    "name": "小明",
    "age": 18,
    "address": "中国"
    }

13.3.2. 后端获取与解析 JSON 键值

当后端代码通过 ConfigUtils.getConfigKey("user.student.info") 获取到这个值时,它得到的是一个 完整的 JSON 字符串

接下来,开发者的任务就是使用 JSON 解析库(如 Jackson 或 FastJSON)将这个字符串 反序列化 为一个 Student Java 对象,然后就可以获取 name, age 等属性了。

这个技巧非常有用,它允许我们用 一个 Key 来管理一组 复杂且相关的 配置,而不是创建 user.student.nameuser.student.age 等三个零散的 Key


13.4. 自定义参数的应用与反查

13.4.1. 演练:新增“请求服务器 IP”动态参数

我们来模拟一个最常见的开发场景:

  • 需求:我们的业务需要调用一个“第三方服务器”的 API,但这个服务器的 IP 地址 未来可能会变
  • 错误做法:在代码里写死 String ip = "127.0.0.1";
  • 正确做法
    1. 在“参数设置”中新增:
      • 参数名称:请求服务器 IP
      • 参数键名:user.request.ip
      • 参数键值:127.0.0.1
    2. 在后端代码中:
      • String ip = ConfigUtils.getConfigKey("user.request.ip");
      • HttpUtils.post(ip, ...)
  • 好处:一年后,第三方服务器 IP 变更。运维人员只需登录后台,将 user.request.ip 的值修改为新 IP,点击“保存”,无需重启,系统的 API 调用立刻切换到新 IP。

13.4.2. [技巧] 反查参数键名的前后端引用

系统里有几十个参数,我怎么知道 sys.index.skinName(默认皮肤)这个参数到底有没有在用?敢不敢删?

答案:全局搜索(Ctrl+Shift+F)

  1. 复制 “参数键名”:sys.index.skinName
  2. 打开后端代码 (IDEA)Ctrl+Shift+F,全局搜索。如果只在 sql 文件中搜到(说明只是在初始化时插入了),而在 .java.xml没有 搜到,说明后端 没用它
  3. 打开前端代码 (VSCode)Ctrl+Shift+F,全局搜索。如果也 没有 搜到,说明前端也 没用它
  4. 结论:这个参数只是一个“历史遗留”,可以 安全删除

13.4.3. 案例剖析:sys.user.initPassword 的应用

我们用 13.4.2 的方法反查 sys.user.initPassword

  • 后端搜索:会发现在 UserImportListener.java(用户导入监听器)中被使用。
  • 前端搜索:会发现在 src/views/system/user/index.vue(用户管理页面 )中被使用。

结论:这个参数在“导入用户”和“新增用户”时都起作用,是 核心参数严禁删除


13.5. “系统内置”参数的保护机制

我们注意到,很多系统参数(如 sys.user.initPassword)的“删除”按钮是 灰色不可用 的。

这就是“系统内置”字段(config_type)提供的“安全锁”功能。

13.5.1. “系统内置”的防误删设计

  • 是什么:它只是一个“是/否”的开关。
  • 为什么:RVP 框架依赖 sys.user.initPassword 才能正常工作。如果一个新来的管理员不知道,随手把它删了,会导致“新增用户”功能 立刻崩溃
  • 作用:将“系统内置”设为“是”,UI 界面就会 自动禁用“删除”按钮,提供一层防误删的“软保护”。

13.5.2. 解除“内置”状态与删除流程

这个“软保护”是可以被解除的。如果(我们假设)你真的 100% 确定要删除一个内置参数:

  1. 步骤一:点击该参数的“修改”。
  2. 步骤二:将“系统内置”的开关从 改为
  3. 步骤三:点击“确定”保存。
  4. 结果:你回到列表,会发现“删除”按钮已经 被激活,可以点击了。

13.6 第十三章总结

本章我们学习了“参数设置”这一“热配置”中心。它与 application.yml 的核心区别在于,它允许我们 无需重启服务,动态修改 业务参数。

  • 核心价值“动态配置” vs “静态配置”yml 放“死”配置(如 DB),“参数设置”放“活”配置(如 IP、开关、初始密码)。
  • 核心机制:系统通过 缓存(Redis)来高性能地读取配置。UI 修改时会自动刷新缓存;如果手动改了数据库,才需要“刷新缓存”。
  • 高级应用Key 必须唯一(如 user.request.ip),Value 可以存储 复杂的 JSON 字符串
  • 安全反查:通过 全局搜索“参数键名”,可以判断一个参数是否仍被前后端代码使用。
  • 安全锁“系统内置” 开关用于在 UI 上禁用“删除”按钮,防止核心参数被误删。