当前位置: 首页 > news >正文

SpringBoot支持动态更新配置文件参数

稿定智能设计202501242152

前言

博主介绍:✌目前全网粉丝3W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技术领域。

涵盖技术内容:Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。

博主所有博客文件目录索引:博客目录索引(持续更新)

视频平台:b站-Coder长路

章节描述

在springboot服务启动之后,想要通过接口来动态修改配置文件参数,实现动态参数配置信息获取。

gitee:https://gitee.com/changluJava/demo-exer/tree/master/SpringBoot/springboot-config/src/main/java/com/changlu/springbootconfig

github:https://github.com/changluya/Java-Demos/tree/master/SpringBoot/springboot-config/src/main/java/com/changlu/springbootconfig

实现接口动态刷新配置参数

image-20250123232945851

代码实现

1、DynamicPropertyUpdater(动态配置项更新器)

自定义DynamicPropertySource动态配置类,接着本质通过environment.getPropertySources()来获取到配置项属性器,后续更新配置项去构造DynamicPropertySource添加到属性器即可完成属性配置覆盖。

package com.changlu.springbootconfig.config;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.stereotype.Component;import java.util.Map;@Component
public class DynamicPropertyUpdater {private static final Logger logger = LoggerFactory.getLogger(DynamicPropertyUpdater.class);private final ConfigurableEnvironment environment;public DynamicPropertyUpdater(ConfigurableEnvironment environment) {this.environment = environment;}/*** 动态更新 Environment 中的配置项值** @param key   配置项的键* @param value 配置项的新值*/public void updateProperty(String key, String value) {logger.info("Updating property: {} = {}", key, value);MutablePropertySources propertySources = environment.getPropertySources();// 添加或更新属性propertySources.addFirst(new DynamicPropertySource(key, value));}/*** 批量动态更新 Environment 中的配置项值* @param properties 配置项*/public void updateProperties(Map<String, String> properties) {for (Map.Entry<String, String> entry : properties.entrySet()) {// 复用单独更新配置项逻辑this.updateProperty(entry.getKey(), entry.getValue());}}/*** 自定义动态属性源*/private static class DynamicPropertySource extends PropertySource<String> {private final String key;private final String value;public DynamicPropertySource(String key, String value) {super("dynamicPropertySource"); // 属性源的名称this.key = key;this.value = value;}@Overridepublic Object getProperty(String name) {// 如果传入的 key 匹配,则返回对应的 valueif (key.equals(name)) {return value;}return null; // 如果不匹配,返回 null}}
}

2、EnvironmentContext(environment管理器)

package com.changlu.springbootconfig.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;@Component
public class EnvironmentContext {@Autowiredprivate Environment environment;public String getProperty(String key, String defaultVal) {return environment.getProperty(key, defaultVal);}
}

3、ConfigController 实现查询配置、更新配置接口

image-20250123233747874

import com.changlu.springbootconfig.config.DynamicPropertyUpdater;
import com.changlu.springbootconfig.config.EnvironmentContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/config")
public class ConfigController {@Autowiredprivate DynamicPropertyUpdater dynamicPropertyUpdater;@Autowiredprivate EnvironmentContext environmentContext;/*** 动态更新配置项的值** @param key   配置项的键* @param value 配置项的新值* @return 更新结果*/@PostMapping("/update")public String updateConfig(@RequestParam String key, @RequestParam String value) {dynamicPropertyUpdater.updateProperty(key, value);return "Config updated successfully: " + key + " = " + value;}/*** 根据 key 获取配置项的值** @param key 配置项的键* @return 配置项的值*/@GetMapping("/get")public String getConfig(@RequestParam String key) {String value = environmentContext.getProperty(key, "未找到对应的配置项");return key + " = " + value;}}

测试

首先在application.properties配置文件中补充一个参数配置:

server.port=8080
changlu.param=parm1

1)启动服务后,查询下参数信息:changlu.param

image-20250123234012131

正常获取到结果值parm1。

2)接着我们调用update更新参数接口

更新changlu.param参数值为:789

image-20250123234204115

3)此时我们再次查询下该参数:

image-20250123234257625

当前已经得到了最新的参数值为:789


实现刷新当前使用的配置文件

目的

在真实场景下,我们会直接上到服务器上修改配置文件参数,接着想要通过调用接口重新加载该配置文件中的所有参数配置信息。

动作:修改配置文件参数项。

发起:调用/refresh接口实现动态刷新。

代码实现

1、SystemPropertyUtil (实现自定义conf配置路径user.dir.conf )

实际场景中,我们的配置文件不会直接打包在jar包中,通常会指定一个配置文件路径。

image-20250123234911039

SystemPropertyUtil:

import java.io.File;public class SystemPropertyUtil {public static void setSystemUserDir() {String dir = System.getProperty("user.dir");String conf = String.format("%s/%s", dir, "conf");File file = new File(conf);if(!file.exists()) {dir = dir.substring(0, dir.lastIndexOf("/"));conf = String.format("%s/%s", dir, "conf");file = new File(conf);if(file.exists()) {System.setProperty("user.dir", dir);}}System.setProperty("user.dir.conf", System.getProperty("user.dir") + "/conf");}
}

接着在启动器服务运行前调用方法来设置全局变量参数user.dir.conf:

image-20250123235050109

SystemPropertyUtil.setSystemUserDir();

此时我们的配置文件在当前工程目录下的conf中:

image-20250123235200056

配置参数值如下:

server.port=8756
changlu.test=444

2、ConfigFileReloader(实现配置文件加载器)

image-20250123235332797

在加载器中,实现了一个方法会去读取user.dir.conf这个变量路径值,此时得到的是/conf的全路径,接着我们去补充配置文件名application.properties即可:

ConfigFileReloader.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.stereotype.Component;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;@Component
public class ConfigFileReloader {private final ConfigurableEnvironment environment;@Autowiredpublic ConfigFileReloader(ConfigurableEnvironment environment) {this.environment = environment;}/*** 重新加载配置文件** @throws IOException 如果文件读取失败*/public void reloadConfig() throws IOException {Properties properties = new Properties();try (FileInputStream fis = new FileInputStream(System.getProperty("user.dir.conf") + "/application.properties")) {properties.load(fis);}MutablePropertySources propertySources = environment.getPropertySources();propertySources.addFirst(new PropertiesPropertySource("dynamicConfig", properties));}
}

3、EnvironmentContext 指定默认读取配置文件路径参数

image-20250123235826147

补充属性源读取路径信息:PropertySource注解中读取静态变量对应conf路径下application.properties

@Component
@PropertySource(value = "file:${user.dir.conf}/application.properties")
public class EnvironmentContext {

4、实现刷新配置文件参数接口

image-20250123235535739

@Autowired
private ConfigFileReloader configFileReloader;/*** 刷新配置文件** @return 配置项的值*/
@GetMapping("/refresh")
public String refreshConfig() throws IOException {configFileReloader.reloadConfig();return "success";
}

后续步骤就是,我们修改conf下的配置文件参数值,然后调用下生效参数接口即可刷新当前应用服务的配置信息。


测试

确认好配置信息:

image-20250123235656206

接着我们启动服务,来调用下获取参数配置信息接口:正常读取到parm1

image-20250123235939279

接着我们手动将配置文件参数修改:

image-20250124000001117

接着调用刷新配置文件接口:

image-20250124000035839

成功刷新,此时我们再去读取下该配置信息:

image-20250124000109778

当前读取到的配置参数为parm2,刷新文件配置项生效!


相关文章:

SpringBoot支持动态更新配置文件参数

前言 博主介绍&#xff1a;✌目前全网粉丝3W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容&#xff1a;Java后端、大数据、算法、分布式微服务、中间件、前端、运维等。 博主所有博客文件…...

开发技巧,vue 中的动态组件的引用 component + is

在项目中很多时候有切换 tab 的场景&#xff0c;一般来说都是用 v-if 或者 v-show 然后根据各种条件来控制显示隐藏。 其实我们可以使用 vue 中的动态组件&#xff0c;也能实现这个效果 <!-- currentTab 改变时组件也改变 --> <component :is"currentTab"…...

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…...

PSD是什么图像格式?如何把PSD转为JPG格式?

在图形设计的世界里&#xff0c;Photoshop 文档&#xff08;PSD&#xff09;格式是 Adobe Photoshop 的原生文件格式&#xff0c;它允许设计师保存图像中的图层、蒙版、透明度和不同色彩模式等信息。对于需要进一步编辑的设计作品来说&#xff0c;PSD 文件提供了极大的灵活性。…...

c语言中mysql_query的概念和使用案例

在 C 语言中&#xff0c;使用 MySQL 数据库需要用到 MySQL C API。mysql_query() 函数是 MySQL C API 中的一个函数&#xff0c;用于执行 SQL 语句。 概念 mysql_query() 函数的原型如下&#xff1a; int mysql_query(MYSQL *mysql, const char *stmt_str)mysql&#xff1a;…...

一次端口监听正常,tcpdump无法监听到指定端口报文问题分析

tcpdump命令&#xff1a; sudo tcpdump -i ens2f0 port 6471 -XXnnvvv 下面是各个部分的详细解释&#xff1a; 1.tcpdump: 这是用于捕获和分析网络数据包的命令行工具。 2.-i ens2f0: 指定监听的网络接口。ens2f0 表示本地网卡&#xff09;&#xff0c;即计算机该指定网络接口捕…...

解决InnoDB: Failing assertion: !lock->recursive

背景&#xff1a; 在arm服务器里运行MySQL5.7.22版本 报错信息 &#xff1a; 2024-11-25T08:07:36.24182508:00 856 [Note] Multi-threaded slave statistics for channel : seconds elapsed 126; events assigned 53431297; worker queues filled over overrun level 0; …...

基于微信小程序的外卖点餐系统设计与实现ssm+论文源码调试讲解

4系统概要设计 4.1概述 本系统后台采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原…...

Helm Chart 实现 Kubernetes 应用的多环境部署与镜像更新

在现代软件开发中,通常需要将应用部署到多个环境(如开发环境、测试环境、生产环境),并且在不同环境中使用不同的配置和镜像版本。Helm Chart 提供了强大的模板化和参数化功能,可以轻松实现多环境部署和镜像更新。本文将详细介绍如何使用 Helm Chart 实现 Kubernetes 应用的…...

“腾讯、钉钉、飞书” 会议开源平替,免费功能强大

在数字化时代&#xff0c;远程办公和线上协作越来越火。然而&#xff0c;市面上的视频会议工具要么贵得离谱&#xff0c;要么功能受限&#xff0c;甚至还有些在数据安全和隐私保护上让人不放心。 今天开源君给大家安利一个超棒的开源项目 - Jitsi Meet&#xff0c;这可是我在网…...

我谈区域偏心率

偏心率的数学定义 禹晶、肖创柏、廖庆敏《数字图像处理&#xff08;面向新工科的电工电子信息基础课程系列教材&#xff09;》P312 区域的拟合椭圆看这里。 Rafael Gonzalez的二阶中心矩的表达不说人话。 我认为半长轴和半短轴不等于特征值&#xff0c;而是特征值的根号。…...

思科交换机telnet配置案例

目录 1.telnet简述2.网络拓扑3.设备说明4.网络配置4.1 电脑PC ip设置4.2 网络交换机telnet配置 5.小结 1.telnet简述 Telnet是远程登录服务的一个协议&#xff0c;该协议定义了远程登录用户与服务器交互的方式。它允许用户在一台联网的计算机上登录到一个远程分时系统中&#…...

机器学习:支持向量机

支持向量机&#xff08;Support Vector Machine&#xff09;是一种二类分类模型&#xff0c;其基本模型定义为特征空间上的间隔最大的广义线性分类器&#xff0c;其学习策略便是间隔最大化&#xff0c;最终可转化为一个凸二次规划问题的求解。 假设两类数据可以被 H x : w T x…...

人工智能前沿技术进展与应用前景探究

一、引言 1.1 研究背景与意义 人工智能作为一门极具变革性的前沿技术&#xff0c;正深刻地改变着人类社会的各个层面。从其诞生之初&#xff0c;人工智能便承载着人类对智能机器的无限遐想与探索。自 20 世纪中叶起&#xff0c;人工智能踏上了它的发展征程&#xff0c;历经了…...

(一)HTTP协议 :请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…...

什么是网络爬虫?Python爬虫到底怎么学?

最近我在研究 Python 网络爬虫&#xff0c;发现这玩意儿真是有趣&#xff0c;干脆和大家聊聊我的心得吧&#xff01;咱们都知道&#xff0c;网络上的信息多得就像大海里的水&#xff0c;而网络爬虫就像一个勤劳的小矿工&#xff0c;能帮我们从这片浩瀚的信息海洋中挖掘出需要的…...

NR_shell运行流程简析

nr_shell 是一套开源 shell 框架&#xff0c;基于框架可创建终端交互功能。 为了记录终端输入指令&#xff0c;以及进行解析处理&#xff0c;nr_shell 提供了一套 cmd 结构体&#xff0c;具体如下&#xff1a;typedef struct static_cmd_function_struct {char cmd[NR_SHELL_CM…...

CSS Fonts(字体)

CSS Fonts(字体) 在网页设计中,字体是传达信息情感和风格的关键元素。CSS(层叠样式表)提供了丰富的字体样式和属性,使得网页设计者能够根据需求选择合适的字体,从而提升用户体验。本文将详细介绍CSS字体相关的知识,包括字体的选择、加载、样式设置等。 字体的选择 选…...

基于Django的Boss直聘IT岗位可视化分析系统的设计与实现

【Django】基于Django的Boss直聘IT岗位可视化分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言&#xff0c;利用Django这一高效、安全的W…...

linux系统中的 scp的使用方法

SCP&#xff08;Secure Copy Protocol&#xff09;是一种通过加密的方式在本地主机和远程主机之间安全地传输文件的协议。 它是基于SSH协议的扩展&#xff0c;允许用户在不同主机之间进行文件复制和传输&#xff0c;是Linux和Unix系统中常用的工具之一。 在嵌入式Linux软件的…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

STM32标准库-ADC数模转换器

文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”&#xff1a;输入模块&#xff08;GPIO、温度、V_REFINT&#xff09;1.4.2 信号 “调度站”&#xff1a;多路开关1.4.3 信号 “加工厂”&#xff1a;ADC 转换器&#xff08;规则组 注入…...

负载均衡器》》LVS、Nginx、HAproxy 区别

虚拟主机 先4&#xff0c;后7...