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.rhkb.cn/news/114650.html

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

相关文章

[ros][ubuntu]ros在ubuntu18.04上工作空间创建和发布一个话题

构建catkin工作空间 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_init_workspace cd ~/catkin_ws/ catkin_make 配置环境变量 echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc 检查环境变量 echo $ROS_PACKAGE_PATH…

详解I2C

I2C&#xff08;也常写作 I I C IIC IIC&#xff0c; I 2 C I^2C I2C&#xff09;&#xff0c;全称为Inter-Integrated Circuit&#xff08;“互连集成电路”&#xff09;&#xff0c;用于在集成电路之间进行短距离数据传输。它由Philips&#xff08;现在的NXP半导体&#xff0…

Python爬虫基础之正则表达式

目录 一、什么是正则表达式&#xff1f; 二、re.compile()编译函数 三、group()获取匹配结果函数 四、常用匹配规则 4.1匹配单个字符 4.2匹配前字符次数 4.3匹配原生字符串 4.4匹配字符串开头和结尾 4.5分组匹配 五、re.match()开头匹配函数 六、re.search()全文搜索…

恒流电路的三种设计方案

作为硬件研发工程师相信对恒流电路不会陌生&#xff0c;本文介绍下三种恒流电路的原理图。 三极管恒流电路 三极管恒流电路 三极管的恒流电路&#xff0c;主要是利用Q2三极管的基级导通电压为0.6~0.7V这个特性&#xff1b;当Q2三极管导通&#xff0c;Q1三极管基级电压被拉低而…

lnmp架构-mysql2

4.mysql 组复制集群 首先对所有的节点重新初始化 因为对节点的数据一致性要求非常高 主从复制的时候 slave只会复制master的binlog日志 就是二进制日志 不会复制relay_log 在server1上 根据实际情况修改主机名和网段 log_slave_updateON 意思就是 当slave的sql线程做完之后…

【Unity-Cinemachine相机】虚拟相机(Virtual Camera)的本质与基本属性

我们可以在游戏进行时修改各个属性&#xff0c;但在概念上&#xff0c;最好将Virtual Camera 当作一种相机行为的“配置文件”&#xff0c;而不是一个组件。 我们的相机有几种行为就为它准备几种虚拟相机&#xff0c;比如角色移动就为它第三人称相机&#xff0c;瞄准就准备一个…

Ubuntu搭建web站点并发布公网访问【内网穿透】

文章目录 前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子域名 前言 网&#xff1a;我们通常说的是互联网&#xff1b…

Java设计模式:四、行为型模式-06:观察者模式

文章目录 一、定义&#xff1a;观察者模式二、模拟场景&#xff1a;观察者模式2.1 观察者模式2.2 引入依赖2.3 工程结构2.4 模拟摇号2.4.1 摇号服务接口2.4.2 摇号返回结果类 三、违背方案&#xff1a;观察者模式3.0 引入依赖3.1 工程结构3.2 添加摇号接口和实现3.2.1 摇号服务…

【锁】定时任务推送数据-redission加锁实例优化

文章目录 redission 加锁代码-有问题优化代码看门狗是什么&#xff1f; redission 加锁代码-有问题 /*** 收货入库物料标签(包装码)推送接口** throws Exception*/public void synReceiveMaterialTags() throws Exception {String tag DateFormatUtils.format(new Date(), &qu…

昨天面试的时候被提问到的问题集合(答案)

1、vue的双向绑定原理是什么&#xff1f;里面的关键点在哪里&#xff1f; Vue的双向绑定原理是基于Object.defineProperty或者Proxy来实现的&#xff0c;其关键点在于数据劫持&#xff0c;即对数据的读取和修改进行拦截&#xff0c;在数据发生变化时自动更新视图 2、实现水平垂…

frida动态调试入门01——定位关键代码

说明 frida是一款Python工具可以方便对内存进行hook修改代码逻辑在移动端安全和逆向过程中常用到。 实战 嘟嘟牛登录页面hook 使用到的工具 1&#xff0c;jadx-gui 2&#xff0c;frida 定位关键代码 使用jadx-gui 进行模糊搜索&#xff0c;例如搜索encyrpt之类的加密关键…

深入解析即时通讯App开发中的关键技术

即时通讯App开发在现代社交和通信领域中扮演着重要的角色。随着移动设备的普及和网络的高速发展&#xff0c;人们对即时通讯工具的需求不断增加。本篇文章将深入探讨即时通讯App开发中的关键技术&#xff0c;帮助读者了解该领域的最新动态和技术趋势。 基础架构和通信协议 现…

《Java极简设计模式》第05章:原型模式(Prototype)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

如何使用Unity制作一个国际象棋

LinnoChess1.0 该项目旨在做一些Unity小游戏项目开发来练练手 如果有更新建议请私信RWLinno 项目地址&#xff1a;https://github.com/RWLinno/LinnoChess 目前效果 能够正常下棋&#xff1b;能够编辑棋盘&#xff1b;能够SL棋局&#xff1b;能够记录棋谱&#xff1b;能够显…

机器学习——聚类算法一

机器学习——聚类算法一 文章目录 前言一、基于numpy实现聚类二、K-Means聚类2.1. 原理2.2. 代码实现2.3. 局限性 三、层次聚类3.1. 原理3.2. 代码实现 四、DBSCAN算法4.1. 原理4.2. 代码实现 五、区别与相同点1. 区别&#xff1a;2. 相同点&#xff1a; 总结 前言 在机器学习…

03-MySQL

1、什么是BufferPool&#xff1f; 1.1、Buffer Pool基本概念 Buffer Pool&#xff1a;缓冲池&#xff0c;简称BP。其作用是用来缓存表数据与索引数据&#xff0c;减少磁盘IO操作&#xff0c;提升效率。 Buffer Pool由缓存数据页(Page)和 对缓存数据页进行描述的控制块 组成,…

【基于空间纹理的残差网络无监督Pansharpening】

Unsupervised Pansharpening method Using Residual Network with Spatial Texture Attention &#xff08;基于空间纹理的残差网络无监督泛锐化方法&#xff09; 近年来&#xff0c;深度学习已经成为最受欢迎的泛锐化工具之一&#xff0c;许多相关方法已经被研究并反映出良好…

day27 String类 正则表达式

String类的getBytes方法 String s "腻害"; byte[] bytes s.getBytes(StandardCharsets.UTF_8); String类的new String方法 String ss "ss我的"; byte[] gbks ss.getBytes("gbk"); String gbk new String(gbks, "gbk"); String类的…

【两周学会FPGA】从0到1学习紫光同创FPGA开发|盘古PGL22G开发板学习之数码管动态显示(五)

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 适用于板卡型号&#xff1a; 紫光同创PGL22G开发平台&#xff08;盘古22K&#xff09; 一&#xff1a;盘古22K开发板&#xff08;紫光同创PGL22G开发…

【防火墙】防火墙NAT Server的配置

Web举例&#xff1a;公网用户通过NAT Server访问内部服务器 介绍公网用户通过NAT Server访问内部服务器的配置举例。 组网需求 某公司在网络边界处部署了FW作为安全网关。为了使私网Web服务器和FTP服务器能够对外提供服务&#xff0c;需要在FW上配置NAT Server功能。除了公网…