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/61281.shtml

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

相关文章

LA@齐次线性方程组解的结构

文章目录 齐次线性方程组解的结构&#x1f388;解的性质齐次线性方程组的解的线性组合还是方程组的解基础解系通解 定理:齐次线性方程组基础解系存在定理齐次线性方程组的基础解系包含的向量个数(秩)&#x1f47a;应用和示例推论1推论2推论3:转置矩阵对的乘积秩的性质非自由未知…

进程Start

Linux中的命令解释器和Windows的程序管理器explorer.exe一样地位,都是在用户态下运行的进程 共享变量发生不同进程间的指令交错&#xff0c;就可能会数据出错 进程只作为除CPU之外系统资源的分配单位 CPU的分配单位是线程 每个进程都有自己的独立用户空间 内核空间是OS内核的…

docker-compose管理创建LNMP服务并运行Wordpress网站平台

文章目录 一&#xff0e;项目环境1. 环境描述2.项目需求 二&#xff0e;部署过程1.安装Docker2.安装Docker加速器3.Docker-Compose安装部署4.准备依赖文件、配置nginx5.配置mysql6.配置php7.编写docker-compose.yml8.验证 三.容器快照&#xff0c;然后将Docker镜像打包成tar包备…

springmvc没有绿标,怎么配置tomcat插件运行?

一、添加插件后&#xff0c;刷新&#xff0c;自动从maven仓库下载tomcat插件 二、写好项目后&#xff0c;添加tomcat配置 三、即可点击绿标运行

关于layui table回显以及选择下一页时记住上一页数据的问题

代码如下 <div class"layui-form-item"><label class"layui-form-label">选择商品</label><div class"layui-input-inline"><input type"text" name"keyword" id"keyword" placehold…

【广州华锐互动】AR昆虫认知学习系统实现对昆虫形态的捕捉和还原

随着科技的不断发展&#xff0c;人们对自然界的认识也在不断加深。在这个过程中&#xff0c;AR&#xff08;增强现实&#xff09;技术的出现为人们带来了全新的体验方式。为此&#xff0c;广州华锐互动开发了AR昆虫认知学习系统&#xff0c;本文将为大家详细介绍这款系统的特点…

jvm的内存划分区域

jvm划分5个区域&#xff1a; java虚拟机栈、本地方法栈、堆、程序计数器、方法区。 各个区各自的作用&#xff1a; 1.本地方法栈&#xff1a;用于管理本地方法的调用&#xff0c;里面并没有我们写的代码逻辑&#xff0c;其由native修饰&#xff0c;由 C 语言实现。 2.程序计数…

HTML基础--Form表单--内联元素

目录 Form表单 表单元素 创建表单 () 文本输入 () 密码输入 单选按钮 () 和 复选框 () 下拉列表 () 和 选项 ()提交按钮 () 重置按钮 () 块元素与行内元素&#xff08;内联元素&#xff09; Form表单 HTML中的表单&#xff08;<form>&#xff09;是一个重要的元…

Kubernetes技术-Kubernetes集群环境搭建准备

1.搭建环境规划 在搭建k8s的时候可以分为两种: 单master集群,故名思意,只有一个master管理节点和多个node节点。如下图所示: 多master集群,故名思意,有多个master管理节点和多个node节点。如下图所示: 2.服务器硬件要求 (1).测试环境要求(教学、研究等环境) Master节点:至…

数字转中文大写金额

有时候&#xff0c;我们需要显示中文大写金额&#xff0c;比如打印银行付款申请单等。 新建一个工程&#xff0c;加入一个标准模块在模块中加入如下代码&#xff0c;窗口中调用 AmountInChineseWords 函数即可。最大解析到百万亿&#xff0c;小数最多解析两位到分。 模块代码…

使用生成式 AI 和 ML 模型进行电子邮件和移动主题行优化

结合使用生成式 AI 和 ML 模型,根据语气和受众自动创建引人注目的主题行和标题,以实现最大程度的参与。 电子邮件和推送通知的主题行和标题在确定参与率方面发挥着重要作用。数字通信需要精心设计引人注目的主题行和简洁的推送通知标题来吸引用户的注意力。营销人员根据要传递…

[蓝桥复盘] 算法赛内测赛2 20230831

[蓝桥复盘] 算法赛内测赛2 20230831 总结新一与基德的身高大战1. 题目描述2. 思路分析3. 代码实现 肖恩的投球游戏加强版1. 题目描述2. 思路分析3. 代码实现 体育健将1. 题目描述2. 思路分析3. 代码实现 小桥的奇异旋律1. 题目描述2. 思路分析3. 代码实现 区间or划分1. 题目描…

css让多个盒子强制自动等宽

1.width: calc( 100 / n% ) 2.display:flex; flex:1;width:100px; 3.display:grid;grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); 但是其中某一个内容较长的时候 会破坏1:1:1的平衡 这个时候发现附件名字过长导致不等比例&#xff0c;通过查看阮一峰flex文…

安防视频监控/视频集中存储/云存储平台EasyCVR平台无法取消共享通道该如何解决?

视频汇聚/视频云存储/集中存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、云存储、智能分析等&#xff0c;视频智能分析平台EasyCVR融合性强、开放度…

智慧景区方案:AI与视频融合技术如何助力景区监管智能化升级?

随着经济的发展&#xff0c;人们对生活的需求也不再局限于温饱层面&#xff0c;越来越多的人们开始追求文化、艺术的高层次需求&#xff0c;旅游也逐渐成为人们日常放松的一种方式。由于我国人口多、易扎堆等特点&#xff0c;景区的运营监管方式也亟需改革。TSINGSEE青犀智能分…

ssm计算机网络课程试卷生成器系统源码

ssm计算机网络课程试卷生成器系统源码099 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm package com.controller;import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays;…

OPENCV实现SURF特征检测

1、SURF优点:SIFT速度慢,一次出现了SURF;2、使用SURF步骤:surf = cv2.xfeatures2d.SURF_create()kp,des = surf.detectAndComputer(img,mask)# -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/8/31 """# -*-

Linux脚本- 执行当前文件下前500个.c文件,并将每个文件对应的执行结果重定向到同名的.ok文件中

需求&#xff1a;执行当前文件下前500个.c文件&#xff0c;并将每个文件对应的执行结果重定向到同名的.ok文件中 以下是一个用于实现该功能的 Bash 脚本。 #!/bin/bash# 计数器&#xff0c;用于限制处理的文件数量 counter0# 遍历当前目录下的所有 .c 文件 for c_file in *.c…

uni-app 编译报错 Error: pages.json解析失败,不符合 json 规范Unexpected token ‘)‘

问题 使用webstorm开发项目时&#xff0c;打开pages.json习惯性ctrlaltl把代码格式了&#xff0c;然后报错了。 接着使用HBuilder编译&#xff0c;但是一直显示在编译中&#xff0c;完全没有反映。重启编译器与重启电脑都没有用。 没管然后编译报错了。 加上逗号再运行还是报…

Uniapp新版本打包后覆盖安装,新增的页面无法跳转,需退出重新启动才可以打开的解决方案

最近写uniapp项目&#xff0c;发现一个坑&#xff0c;在新版本覆盖安装后直接打开APP&#xff0c;新增的页面竟然无法跳转&#xff0c;需要重新启动才可以正常打开&#xff0c;在网上查了很多方法&#xff0c;最终总结下来有以下几点&#xff1a; 1.看打的是debug包还是releas…