Springboot 接口方式硬通知实现ConfigurationProperties 、@Value 动态刷新

前言


看到这个文章标题,也许有的看官就觉得很多余, 

因为Nacos 可以设置    @NacosValue(value = "${XXX}",autoRefreshed = true) 实现动态刷新;

又因为cloud config的@RefreshScope   实现动态刷新;

还有阿波罗...等

这些玩意的原理其实都很简单,简单说 就是检测到配置文件的修改项后,发布内容变更事件,然后重新刷新绑定值。

那如果我说不准用这些东西呢?

现在就是一个老项目,不给整合这些阿猫阿狗,我想问阁下应该如何应对?

ps: 最近有个朋友在整改旧项目,做了一套小的配置中心系统,在这个配置平台系统上,通过页面能够动态修改刷新配置值。  做完后,这个朋友有些心得,想分享一下。

不多说,开搞。

正文

我们结合示例玩一下。

@Value

@ConfigurationProperties


 

对应代码:
 

@Component
public class YouInfos {@Value("${u.infos.name}")private String name;@Value("${u.infos.age}")private Integer age;@Autowiredprivate Environment env;public String getName() {return env.getProperty("u.infos.name");}public Integer getAge() {return Integer.valueOf(Objects.requireNonNull(env.getProperty("u.infos.age")));}public void setName(String name) {this.name = name;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "YouInfos{" +"name='" + name + '\'' +", age=" + age +'}';}
}
@Component
@ConfigurationProperties(prefix = "my.infos")
public class MyInfos {private String name;private Integer age;@Autowiredprivate Environment env;public String getName() { return env.getProperty("my.infos.name"); }public void setName(String name) { this.name = name; }public Integer getAge() { return age; }public void setAge(Integer age) { this.age = age; }@Overridepublic String toString() {return "MyInfos{" +"name='" + name + '\'' +", age=" + age +'}';}
}

对应application.yml的配置(当然也可以是自己额外的配置文件值):

my:infos:name: JCcccage: 18u:infos:name: Doliage: 25

细心的看官,看到这里,已经发现了一些不同。

是的 我把配置项的属性字段的get方法,魔改了一下,写成了重新在 Environment 再拿一次。

简单来说,我希望哪些字段属性是可以达到获取实时数据的,那我就改掉这个字段属性的get方法,让它从头再来过,去 Environment 再拿一次 自己。

接下来,就是我们怎么去改 Environment 里面的key属性值。

结合源码实操玩一下。

① 把环境配置属性拿出来 

  private static ConfigurableEnvironment environment;

  MutablePropertySources propertySources   = environment.getPropertySources();

可以看到,这8组配置属性里面, 有一组的名字包含了 application.yml 。

点进去看看是什么:

没错,就是我们的yml 的key 以及value 。

看到这, 大家思路已经比较开明了吧, 我们把这个玩意拿出来, 我们改了哪些key就对应改哪些key(当然新增了哪些,也可以对应去搞)。

看一下这个玩意MutablePropertySources  的源码:

好好好,这么玩是吧,又private 又final 。

这样的情况,我们如何应对?

那当然是最简单的暴力破解 ,反射了: 

            Field valueFieldOfPropertySources = MutablePropertySources.class.getDeclaredField("propertySourceList");
            //设置value属性的访问权限为true
            valueFieldOfPropertySources.setAccessible(true);
            //获取对象上的value属性的值
            List<PropertySource<?>> valueList = (List<PropertySource<?>>) valueFieldOfPropertySources.get(propertySources);
 

这样我们就把这八组的值拿出来了, 然后就遍历,然后把这个 OriginTrackedMapPropertySource(yml的配置值) 拿出来,改完值,再丢回去, 完事。

代码:

MyRefreshConfigUtil.java
 

import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/*** @author JCccc 2023-08-01*/@Component
public class MyRefreshConfigUtil implements EnvironmentAware {private static ConfigurableEnvironment environment;public static void refreshValue(String key, Object newValue)  {try {MutablePropertySources propertySources   = environment.getPropertySources();Field valueFieldOfPropertySources = MutablePropertySources.class.getDeclaredField("propertySourceList");//设置value属性的访问权限为truevalueFieldOfPropertySources.setAccessible(true);//获取对象上的value属性的值List<PropertySource<?>> valueList = (List<PropertySource<?>>) valueFieldOfPropertySources.get(propertySources);for (PropertySource<?> propertySource :valueList){if (propertySource instanceof OriginTrackedMapPropertySource){Map<String, Object> source = (Map<String, Object>) propertySource.getSource();Map<String, Object> map = new HashMap<>(source.size());map.putAll(source);map.put(key, newValue);environment.getPropertySources().replace(propertySource.getName(), new OriginTrackedMapPropertySource(propertySource.getName(), map));}}} catch (Exception e) {e.printStackTrace();}}@Overridepublic void setEnvironment(Environment environment) {MyRefreshConfigUtil.environment = (ConfigurableEnvironment) environment;}
}

代码简析 :


那么我们再暴露出一个api 接口 ,满足key 和 value的实时刷新(可以写成批量,这里就简单写个单个key意思下):
 

    @GetMapping("/doRefresh")public String doRefresh(@RequestParam String key ,@RequestParam String value) {MyRefreshConfigUtil.refreshValue(key, value);return  "refresh success";}

也写个简单的获取配置值接口,看看整体的效果:
 

    @AutowiredMyInfos myInfos;@AutowiredYouInfos youInfos;@GetMapping("/getInfos")public String getInfos() {String myName = myInfos.getName();String yourName = youInfos.getName();return myName+"---"+yourName;}

服务跑起来,先看看我们的配置值:

接下来,我们去修改配置项,然后检测到了配置项哪些key做了改动(这些需要配合前端页面系统化去做比较流畅,就像是一些配置中心页面的保存按钮),然后调用我们的key刷新通知接口:

 

再调用看下我们的配置值:

好了,就这样吧。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/66860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python爬虫】13.吃什么不会胖(爬虫实操练习)

文章目录 前言项目实操明确目标分析过程代码实现 前言 吃什么不会胖——这是我前段时间在健身时比较关注的话题。 相信很多人&#xff0c;哪怕不健身&#xff0c;也会和我一样注重饮食的健康&#xff0c;在乎自己每天摄入的食物热量。 不过&#xff0c;生活中应该很少有人会…

景联文科技:高质量AI数据标注助力大语言模型训练,推动人工智能落地应用

大语言模型在各类LLM新技术的融会贯通下&#xff0c;不断加速Instruction-tuning、RLHF、思维链等新技术在大语言模型中的深度应用&#xff0c;人工智能技术以惊人的速度不断进化。 大语言模型&#xff08;LLM&#xff09;是一种基于深度学习技术和海量文本数据&#xff0c;它们…

Leetcode:349. 两个数组的交集【题解超详细】

题目 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 难度&#xff1a;简单 题目链接&#xff1a;349.两个数组的交集 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,…

【08期】ArrayList常见面试题

简介 ArrayList是我们开发中非常常用的数据存储容器之一&#xff0c;其底层是数组实现的&#xff0c;我们可以在集合中存储任意类型的数据&#xff0c;ArrayList是线程不安全的&#xff0c;非常适合用于对元素进行查找&#xff0c;效率非常高。 线程安全性 对ArrayList的操作…

百度文心一言GPT免费入口也来了!!!

文心一言入口地址&#xff1a;文心一言能力全面开放 文心一言是百度全新一代知识增强大语言模型&#xff0c;文心大模型家族的新成员&#xff0c;能够与人对话互动&#xff0c;回答问题&#xff0c;协助创作&#xff0c;高效便捷地帮助人们获取信息、知识和灵感。 文心一言的技…

Python 分析HTTP的可靠性

在这篇文章中&#xff0c;我们将介绍如何使用 Python 来分析代理服务提供商的可靠性。代理服务在许多场景中都非常有用&#xff0c;例如突破地理限制、保护隐私和提高网络安全性。然而&#xff0c;并非所有的代理服务提供商都是可靠的。因此&#xff0c;我们将使用 Python 来测…

【传输层】TCP -- 三次握手四次挥手 | 可靠性与提高性能策略

超时重传机制连接管理机制三次握手四次挥手滑动窗口拥塞控制延迟应答捎带应答面向字节流粘包问题TCP异常情况TCP小结基于TCP应用层协议理解 listen 的第二个参数 超时重传机制 主机A发送数据给B之后&#xff0c;可能因为网络拥堵等原因&#xff0c;数据无法到达主机B&#xff1…

3DCAT携手华为,打造XR虚拟仿真实训实时云渲染解决方案

2023年5月8日-9日&#xff0c;以 因聚而生 众志有为 为主题的 华为中国合作伙伴大会2023 在深圳国际会展中心隆重举行。本次大会汇聚了ICT产业界的广大新老伙伴朋友&#xff0c;共同探讨数字化转型的新机遇&#xff0c;共享数字化未来的新成果。 华为中国合作伙伴大会2023现场&…

在线音乐播放器测试报告

文章目录 一、项目背景二、项目功能三、测试目的四、测试环境五、测试计划5.1 功能测试5.2 自动化测试 六、测试结果 一、项目背景 今天&#xff0c;市面上的音乐播放器种类繁多同时功能强大。一个单纯的音乐播放器可能不再单纯只是音乐播放的功能&#xff0c;而是更多地集短视…

对战ChatGPT,创邻科技的Graph+AI会更胜一筹吗?

大模型&#xff08;大规模语言模型&#xff0c;即Large Language Model&#xff09;的应用已经成为千行百业发展的必然。特定领域或行业中经过训练和优化的企业级垂直大模型则成为大模型走下神坛、真正深入场景的关键之路。 但是&#xff0c;企业级垂直大模型在正式落地应用前…

机器人中的数值优化(十一)——高斯牛顿法、LMF方法、Dogleg方法

本系列文章主要是我在学习《数值优化》过程中的一些笔记和相关思考&#xff0c;主要的学习资料是深蓝学院的课程《机器人中的数值优化》和高立编著的《数值最优化方法》等&#xff0c;本系列文章篇数较多&#xff0c;不定期更新&#xff0c;上半部分介绍无约束优化&#xff0c;…

【FPGA零基础学习之旅#11】数码管动态扫描

&#x1f389;欢迎来到FPGA专栏~数码管动态扫描 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;FPGA学习之旅 文章作者技术和水平有限&#xff0c;如果文中出现错误&#xff0c;希望大家能指正…

HarmonyOS—UI开发性能提升的推荐方法

注&#xff1a;本文转载自HarmonyOS官网文档 开发者若使用低性能的代码实现功能场景可能不会影响应用的正常运行&#xff0c;但却会对应用的性能造成负面影响。本章节列举出了一些可提升性能的场景供开发者参考&#xff0c;以避免应用实现上带来的性能劣化。 使用数据懒加载 开…

如何熟练使用vector?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

Blender 围绕自身的原点旋转与游标旋转

默认情况下的旋转是&#xff0c;R后旋转是物体自身的原点旋转 可以修改为围绕游标旋转&#xff0c;通过旋转R时 局部与全局坐标 全局的坐标不会变 局部的会随着物体的旋转变化 如果平稳时GZZ会在全局到局部坐标之间切换 或在局部到全局之间的切换 学习视频&#xff1a;【基础…

PaddleNLP使用Vicuna

LLaMA 模型 LLaMa 是一个大型语言模型&#xff0c;由 Meta 开源。它的全称是 Large Language Model Meta AI&#xff0c;参数量从 70 亿到 650 亿不等。例如&#xff0c;130 亿参数的 LLaMA 模型在大多数基准上可以胜过参数量达 1750 亿的 GPT-3&#xff0c;而且可以在单块 V1…

go语言-channel

环形缓存可以降低GC得开销 channel使用得是mutex锁 互斥锁并不是排队发送/接收数据 互斥锁保护的hchan结构体本身 Channel并不是无锁的 底层发送原理 c<- 关键字是一个语法糖 编译阶段&#xff0c;会把 c<- 转化为 runtime.chansend10 chansend10会调用 charsend0 方法…

使用 FastChat 运行 CodeLlama-7b-Instruct-hf

使用 FastChat 运行 CodeLlama-7b-Instruct-hf 1. 确认 FactChat 支持的 Model2. 升级依赖3. 启动 controller4. 启动 CodeLlama5. 启动 api server6. VSCode 中使用 CodeLlama 1. 确认 FactChat 支持的 Model 访问 model_support.md&#xff0c;确认 codellama/CodeLlama-7b-…

【100天精通Python】Day53:Python 数据分析_NumPy数据操作和分析进阶

目录 1. 广播 2 文件输入和输出 3 随机数生成 4 线性代数操作 5 进阶操作 6 数据分析示例 1. 广播 广播是NumPy中的一种机制&#xff0c;用于在不同形状的数组之间执行元素级操作&#xff0c;使它们具有兼容的形状。广播允许你在不显式复制数据的情况下&#xff0c;对不同…

小程序数据导出文件

小程序josn数据生成excel文件 先从下载传送门将xlsx.mini.min.js拷贝下来&#xff0c;新建xlsx.js文件放入小程序项目文件夹下。 const XLSX require(./xlsx)//在需要用的页面中引入// 定义导出 Excel 报表的方法exportData() {const that thislet newData [{time:2021,val…