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

2023-11-11

前言


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

因为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;
    @Autowired
    private 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;
    }
    @Override
    public String toString() {
        return "YouInfos{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
@Component
@ConfigurationProperties(prefix = "my.infos")
public class MyInfos {
    private String name;
    private Integer age;
    @Autowired
    private 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; }

    @Override
    public String toString() {
        return "MyInfos{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

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

my:
  infos:
    name: JCccc
    age: 18

u:
  infos:
    name: Doli
    age: 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属性的访问权限为true
            valueFieldOfPropertySources.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();
        }
    }

    @Override
    public 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";
    }

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

    @Autowired
    MyInfos myInfos;
    @Autowired
    YouInfos youInfos;

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

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

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

 

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

好了,就这样吧。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Springboot 接口方式硬通知实现ConfigurationProperties 、@Value 动态刷新 的相关文章

  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • 如何使用 Java 中的 Web 服务(例如 Axis2)发送复杂对象的数组或集合?

    我对 SOAP Web 服务还比较陌生 虽然我完成了一些较小的 Web 服务项目 但我偶然从来不需要返回 或用作参数 复杂 对象的数组或集合 当我尝试这样做时 根据我的 SOAP 绑定风格 我会得到不同的奇怪行为 当我使用RPC 文字 我可
  • 插入最大日期(独立于数据库)

    在我的本地设置中 我使用一个简单的 H2 数据库 托管 解决方案将有另一个 类似但不相同 数据库 我需要将最大可能日期插入到日期时间列中 我尝试使用 Instant MAX 但是 这会导致列中出现 169104626 12 11 20 08
  • 使用 JPA Criteria API 进行分页的总行数

    我正在系统中为实体实现 高级搜索 功能 以便用户可以使用该实体的属性上的多个条件 eq ne gt lt 等 来搜索该实体 我正在使用 JPA 的 Criteria API 动态生成 Criteria 查询 然后使用setFirstResu
  • 正则表达式拆分数字和字母组,不带空格

    如果我有一个像 11E12C108N 这样的字符串 它是字母组和数字组的串联 如何在中间没有分隔符空格字符的情况下分割它们 例如 我希望分割结果为 tokens 0 11 tokens 1 E tokens 2 12 tokens 3 C
  • JAVA - Xuggler - 组合 MP3 音频文件和 MP4 电影时播放视频

    使用 JAVA 和 Xuggler 以下代码组合 MP3 音频文件和 MP4 电影文件并输出组合的 mp4 文件 我希望在合并音频和视频文件时应自动播放输出视频文件 String inputVideoFilePath in mp4 Stri
  • Cassandra java驱动程序协议版本和连接限制不匹配

    我使用的java驱动程序版本 2 1 4卡桑德拉版本 dsc cassandra 2 1 10cql 的输出给出以下内容 cqlsh 5 0 1 Cassandra 2 1 10 CQL spec 3 2 1 Native protocol
  • 如何使用 Maven 打包并运行具有依赖项的简单命令行应用程序?

    我对 java 和 Maven 都是全新的 所以这可能非常简单 如果我遵循maven2hello world此处的说明 http maven apache org guides getting started maven in Five m
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • 普罗米修斯指标 - 未找到

    我有 Spring Boot 应用程序 并且正在使用 vertx 我想监控服务和 jvm 为此我选择了 Prometheus 这是我的监控配置类 Configuration public class MonitoringConfig Bea
  • 有没有一种快速方法可以从 Jar/war 中删除文件,而无需提取 jar 并重新创建它?

    所以我需要从 jar war 文件中删除一个文件 我希望有类似 jar d myjar jar file I donot need txt 的内容 但现在我能看到从 Linux 命令行执行此操作的唯一方法 不使用 WinRAR Winzip
  • Java整数双除法混淆[重复]

    这个问题在这里已经有答案了 方案1 int sum 30 double avg sum 4 result is 7 0 not 7 5 VS 方案2 int sum 30 double avg sum 4 0 Prints lns 7 5
  • Jersey 客户端请求中未设置 Content-Length-Header

    我正在使用 Jersey Client 访问网络服务 如下所示 response r accept MediaType TEXT PLAIN TYPE header content length 0 post String class 其中
  • 我可以创建自定义 java.* 包吗?

    我可以创建一个与预定义包同名的自己的包吗在Java中 比如java lang 如果是这样 结果会怎样 这难道不能让我访问该包的受保护的成员 如果不是 是什么阻止我这样做 No java lang被禁止 安全管理器不允许 自定义 类java
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • javafx android 中的文本字段和组合框问题

    我在简单的 javafx android 应用程序中遇到问题 问题是我使用 gradle javafxmobile plugin 在 netbeans ide 中构建了非常简单的应用程序 其中包含一些文本字段和组合框 我在 android
  • 为什么这个作业不起作用?

    我有课Results which extends ArrayList
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话
  • GUI Java 程序 - 绘图程序

    我一直试图找出我的代码有什么问题 这个想法是创建一个小的 Paint 程序并具有红色 绿色 蓝色和透明按钮 我拥有我能想到的让它工作的一切 但无法弄清楚代码有什么问题 该程序打开 然后立即关闭 import java awt import

随机推荐

  • idea中java程序打jar包的两种方式(超详细)

    java程序打成的jar包有两种类型 一种是可直接执行的runnable jar文件 另一种是包含多个主类 运行时需要指定主类全类名的jar包 下面我们细说在idea中两种jar包的打包方法及执行jar包时的命令 第一种 含多个主类的jar
  • 【机器学习】最优化方法:梯度下降法

    1 概念 梯度下降法 Gradient Descent 又称最速下降法 Steepest descent 是一种常用的一阶优化方法 是一种用于求解无约束最优化问题的最常用的方法 它选取适当的初始值 并不断向负梯度方向迭代更新 实现目标函数的
  • 颜色空间YCrCb

    YCrCb即YUV 主要用于优化彩色视频信号的传输 使其向后相容老式黑白电视 与RGB视频信号传输相比 它最大的优点在于只需占用极少的频宽 RGB要求三个独立的视频信号同时传输 其中 Y 表示明亮度 Luminance或Luma 也就是灰阶
  • 深度学习网络__tensorflow__第四讲__神经网络优化

    本文为转载北京大学 人工智能实践 Tensorflow笔记 课程 链接 https www icourse163 org course PKU 1002536002 Tensorflow 笔记 第四讲 神经网络优化 4 1 神经元模型 用数
  • VirtualBox的下载与安装

    文章来源 http sh qihoo com pc 91c30d12ff6bd60e9 cota 4 tj url xz sign 360 e39369d1 refer scene so 1 1 下载VirtualBox VirtualBo
  • 2.4.10 Profile HEA参数

    最后更新2021 07 23 HEA有两种使用方式 第一种是独立作为虚拟以太网支持卡使用 第二种是作为普通网卡 性能更高 无论哪一种方式都需要对HEA做一些特殊的初始化设置 并且是互斥的 我们先来看看系统中HEA的状态 操作如 lt 图 2
  • vulhub安装时的问题

    在安装vulhub时 出现cannot import transport或者是无法导入其他的模块 从网上找到的方法都尝试之后均不行 这个文件夹明明存在 但是他就是说找不到 解决方法 在使用pip进行安装的时候 网上找的他们都是直接默认安装的
  • python __doc__方法

    doc 方法是python的内置方法之一 该方法通常会输出指定对象中的注释部分 NB 注意 后面的部分表示输出结果 代码如下 class Debug This is a class for debugging def init self T
  • ESP32-C3入门教程 基础篇(一、ADC采样)

    经过前面的折腾 设计好了自己的测试开发板 搭建好了开发环境 然后正式开始进行功能测试了 测试顺序先从简单的开始吧 一步一步来 目录 前言 1 ADC采样示例测试 1 1 DMA连续采样 1 2 单次采样 1 3 测试源码 2 ESP32 C
  • linux之perf(2)list事件

    Linux之perf 2 list事件 Author Onceday Date 2023年9月3日 漫漫长路 才刚刚开始 参考文档 Tutorial Perf Wiki kernel org perf list 1 Linux manual
  • DevOps理念:开发与运维的融合

    在现代软件开发领域 DevOps 不仅仅是一个流行的词汇 更是一种文化 一种哲学和一种方法论 DevOps 的核心理念是通过开发和运维之间的紧密合作 实现快速交付 高质量和持续创新 本文将深入探讨 DevOps 文化的重要性 原则以及如何在
  • C语言 - 整形在内存中的存储方式

    一 以补码的形式存储在内存当中 1 有符号型的整数二进制首位0表示正 1表示负数 2 正数的原码 反码 补码都相同 如 3 负数的反码为原码的首位数不变 其他位按位取反所得 补码为反码 1 如 当然 要得到负数的原码 可以反过来 即补码 1
  • 基于SpringCloud的Microservices架构实战案例-在线API管理

    simplemall项目前几篇回顾 1基于SpringCloud的Microservices架构实战案例 序篇 2基于SpringCloud的Microservices架构实战案例 架构拆解 3基于SpringCloud的Microserv
  • C语言读取load格式文件,求指导,如何用c语言实现读取*.raw格式图像

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这个程序是读取jpg图像的 后续加上jpg图像打开和存放 include include include include include define SOI 0xD8 文件头 define E
  • 【Redis篇】Redis缓存之双写一致性

    1 引言 redis做为缓存 mysql的数据如何与redis进行同步呢 本质上问的就是双写一致性 注意 回答这个问题前一定要结合自己的业务背景 分两种情况 一个是你的业务一致性要求高 另一个是你的业务允许延迟一致 2 双写一致性 2 1
  • 大数据技术之数据质量管理

    一 数据质量概述 1 数据质量简介 数据质量的高低代表了该数据满足数据消费者期望的程度 这种程度基于他们对数据的使用预期 只有达到数据的使用预期才能给予管理层正确的决策参考 数据质量管理作为数据仓库的一个重要模块 主要可以分为数据的健康标准
  • 前端实现导出excel表格(单行表头)

    需求 实现勾选行导出为表格 一 安装插件 npm install save file saver xlsx 运行项目报如下警告的话 运行npm install xlsx 0 16 0 save 来降低版本号 最初我安装的版本号是0 18 1
  • android天气预报开题报告,开题报告-基于Android手机移动天气预报系统.doc

    毕业设计 论文 开题报告 题目 基于Android手机移动天气预报系统 一 选题依据 目的和意义 天气预报就是对未来时期内天气变化的预先估计和报告 它是根据大气科学的基本理论和技术对每一地区的未来天气做出分析和预测 这是大气科学为国民经济建
  • 比尔盖茨现身西雅图SAS 2007“治疗失眠”

    结束了4月18 21号的访华活动 比尔盖茨又现身在了西雅图5月8号开始的为时两天的第八届微软战略合作伙伴高峰会议上 Strategic Account Summit Conference 这次会议请来了众多重量级的大腕嘉宾 包括负责微软网络
  • Springboot 接口方式硬通知实现ConfigurationProperties 、@Value 动态刷新

    前言 看到这个文章标题 也许有的看官就觉得很多余 因为Nacos 可以设置 NacosValue value XXX autoRefreshed true 实现动态刷新 又因为cloud config的 RefreshScope 实现动态刷