springboot - 实现动态刷新配置

news2024/12/24 3:31:03

自定义的配置数据源,继承自Spring框架的 MapPropertySource 类,从一个名为 my.properties 的文件中读取配置信息,并在每10秒钟刷新一次。

这里不加@Component,是因为:
FilePropertiesSource filePropertiesSource = new FilePropertiesSource();
// 属性源是按照添加的顺序进行合并的,后添加的属性源中的属性会覆盖前面添加的属性源中的同名属性。
// 因此,为了确保我们自定义的属性源中的属性优先级最高,我们需要将它添加到属性源列表的最后。这样就能保证后添加的属性源中的属性值会覆盖之前的同名属性。
environment.getPropertySources().addLast(filePropertiesSource);


import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.MapPropertySource;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 *
 * 自定义的配置数据源,继承自Spring框架的 MapPropertySource 类,从一个名为 my.properties 的文件中读取配置信息,并在每10秒钟刷新一次。
 * @author Administrator
 */
@Slf4j
//@Component
public class FilePropertiesSource extends MapPropertySource {

    private static final Logger logger = LoggerFactory.getLogger(FilePropertiesSource.class);


    private static final String CONFIG_FILE_NAME = "my.properties";
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public FilePropertiesSource() {
        super("filePropertiesSource", new HashMap<>());
    }

    /**
     * 从配置文件中读取配置,10s 更新一次
     */
    @PostConstruct
    @Scheduled(fixedRate = 10_000)
    public void refreshSource() throws IOException {
        logger.info("开始读取配置文件 {}", CONFIG_FILE_NAME);
        InputStream inputStream = getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
        if (inputStream == null) {
            throw new FileNotFoundException("配置文件 " + CONFIG_FILE_NAME + " 不存在");
        }

        Map<String, String> newProperties = new HashMap<>();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (StringUtils.isEmpty(line) || line.startsWith("#")) {
                    continue;
                }
                String[] pair = StringUtils.split(line, "=");
                if (pair == null || pair.length != 2) {
                    logger.warn("忽略配置项 {}", line);
                    continue;
                }
                String key = pair[0].trim();
                String value = pair[1].trim();
                logger.debug("读取配置项 {} = {}", key, value);
                newProperties.put(key, value);
            }
        } catch (IOException e) {
            logger.error("读取配置文件 {} 出现异常:{}", CONFIG_FILE_NAME, e.getMessage(), e);
            throw e;
        }

        synchronized (this) {
            source.clear();
            source.putAll(newProperties);
        }

        logger.info("读取配置文件完成,共读取 {} 个配置项,时间 {}", newProperties.size(), LocalDateTime.now().format(DATE_TIME_FORMATTER));
    }


    /**
     * 覆盖 getProperty 方法,实现实时获取配置
     *
     * @param key 配置项的 key
     * @return 配置项的值
     */
    @Override
    public Object getProperty(String key) {
        return source.get(key);
    }
}

定义一个Spring配置类,定义了一个名为 filePropertiesSource 的Bean,并将其加入到环境变量中。


import com.lfsun.bootdynamicenv.config.FilePropertiesSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;


/**
 * 一个Spring配置类,定义了一个名为 filePropertiesSource 的Bean,并将其加入到环境变量中。
 */
@Configuration
public class AutoConfig {
    @Bean
    public FilePropertiesSource filePropertiesSource(ConfigurableEnvironment environment) {
        FilePropertiesSource filePropertiesSource = new FilePropertiesSource();
        // 属性源是按照添加的顺序进行合并的,后添加的属性源中的属性会覆盖前面添加的属性源中的同名属性。
        // 因此,为了确保我们自定义的属性源中的属性优先级最高,我们需要将它添加到属性源列表的最后。这样就能保证后添加的属性源中的属性值会覆盖之前的同名属性。
        environment.getPropertySources().addLast(filePropertiesSource);
        return filePropertiesSource;
    }
}

为了方便直接用启动类作为控制层

@DependsOn(“filePropertiesSource”) 依赖于filePropertiesSource,以实现刷新配置。
@EnableScheduling 实现定时刷新
private String userName; 会被计算机名称覆盖,计算机名称优先级最高

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


@DependsOn("filePropertiesSource")
@EnableScheduling
@RestController
@SpringBootApplication
public class Application {
    @Autowired
    private Environment environment;

    @Value("${user-name}")
    private String userName;


    @GetMapping(path = "get")
    public String getProperty(String key) {
        return userName + "  |  " + environment.getProperty(key);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

实现效果

在这里插入图片描述
访问:http://localhost:8080/get?key=my-user-id
在这里插入图片描述
可见修改user-name无效,被计算机名称所覆盖。
这时候修改my-user-id=
在这里插入图片描述
再访问:http://localhost:8080/get?key=my-user-id
在这里插入图片描述
已实现刷新:

ext:

@PostConstruct:

用于指定在依赖注入完成后需要执行的初始化方法。具体来说,当Spring容器完成对一个bean的依赖注入后,会调用该bean中使用了@PostConstruct注解的方法。

例如,如果在一个类中定义了一个方法,并在该方法上添加了@PostConstruct注解,那么当Spring容器初始化该类时,会自动调用该方法,以完成一些必要的初始化操作。

@PostConstruct注解的方法不能带有任何参数,也不能有返回值,因为Spring不会使用这些返回值。如果需要返回一些状态信息,可以使用类成员变量来保存这些信息。另外需要注意的是,@PostConstruct注解只能用于非静态方法。

@Scheduled(fixedRate = 10_000)

@Scheduled是一个Spring框架提供的注解,用于实现基于时间的任务调度。通过在方法上添加@Scheduled注解,并指定相应的属性,可以使得该方法在指定的时间间隔内自动执行。

例如,@Scheduled(fixedRate = 10_000)表示每隔10秒执行一次该方法。fixedRate属性指定了执行方法的时间间隔,单位为毫秒。除此之外,还可以使用cron表达式指定执行时间,如@Scheduled(cron = “0 0 12 * * ?”)表示每天中午12点执行一次该方法。

需要注意的是,使用@Scheduled注解的方法必须是无参方法,且返回类型为void或Future。如果需要传递参数或返回结果,可以使用实例变量或方法返回值进行传递。同时,为了使得@Scheduled注解生效,需要在启动类上面@EnableScheduling

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

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

相关文章

辨析 总结PMP各种BS结构

OBS 组织分解结构、BOM 物料清单、WBS工作分解结构、RBS 资源分解结构、RBS 风险分解结构、RAM 责任分匹配矩阵辨析 组织分解结构 OBS&#xff08;Organizational Breakdown Structure&#xff09; 描述了执行组织的层次结构&#xff0c;以便把工作包同执行组织单元相关联 物料…

电子邮件SDK:MailBee.NET 12.3.1 Crack

MailBee.NET 对象捆绑包包括SMTP、POP3、IMAP、EWS、安全、反垃圾邮件、Outlook 转换器、地址验证器、PDF组件以及BounceMail、HTML、MIME、ICalVCard组件&#xff0c;这些组件是一项常用功能。 MailBee.NET Objects是一组强大且功能丰富的 .NET 组件&#xff0c;用于创建、发送…

Haffman编码(算法导论)

上次算法导论课讲到了Haffman树&#xff0c;笔者惊叹于Haffman编码的压缩效果&#xff0c;故想自己亲自动手尝试写一个极简的Haffman压缩程序。 首先&#xff0c;我们来了解一下什么是Haffman编码 Haffman编码 赫夫曼编码可以很有效地压缩数据&#xff1a;通常可以节省20%&am…

UNIX环境高级编程——进程关系

9.1 引言 本章详细说明进程组以及会话的概念&#xff0c;还将介绍登录shell&#xff08;登录时所调用的&#xff09;和所有从登录shell启动的进程之间的关系。 9.2 终端登录 9.3 网络登录 9.4 进程组 每个进程除了有一进程ID之外&#xff0c;还属于一个进程组&#xff0c;进…

一曲微茫度余生 ——川剧《李亚仙》唱响香港西九戏曲中心

2023年4月28日晚&#xff0c;香港西九戏曲中心灯火辉煌。重庆市川剧院携手成都市川剧研究院带来的川剧《李亚仙》首场演出在这个为戏曲而设的世界级舞台重磅上演。 此次访演受香港西九戏曲文化中心的邀请&#xff0c;原重庆市文化和旅游发展委员会党委书记、主任刘旗带队&…

『LogDashboard』.NET开源的日志面板——登录授权页面扩展

&#x1f4e3;读完这篇文章里你能收获到 了解LogDashboard扩展开源项目——LogDashboard.Authorization掌握LogDashboard扩展内置登录页的使用方式 文章目录 一、LogDashbaord介绍1. 功能支持2. 快速开始 二、LogDashboard.Authorization1. 功能介绍2. 项目接入3. 更多示例 一…

Python语法学习

目录 Openmv用micro python开发的原因 print函数 列表 元组 判断 if...else... if...elif...else 循环 for循环 while循环 强制类型转换 点灯之路 点个不同颜色的闪烁LED 本文章仅作为个人的Openmv学习笔记&#xff0c;有问题欢迎指正~ Openmv用micro python开发…

【MPC|云储能】基于模型预测控制(MPC)的微电网调度优化的研究(matlab代码)

目录 1 主要内容 2 程序难点及问题说明 3 部分程序 4 下载链接 1 主要内容 该程序分为两部分&#xff0c;日前优化部分——该程序首先根据《电力系统云储能研究框架与基础模型》上面方法&#xff0c;根据每个居民的实际需要得到响应储能充放电功率&#xff0c;优化得到整体…

性能测评:阿里云服务器ECS通用型g8i实例CPU内存安全存储

阿里云服务器ECS通用型实例规格族g8i采用2.7 GHz主频的Intel Xeon(Sapphire Rapids) Platinum 8475B处理器&#xff0c;3.2 GHz睿频&#xff0c;g8i实例采用阿里云全新CIPU架构&#xff0c;可提供稳定的算力输出、更强劲的I/O引擎以及芯片级的安全加固。阿里云百科分享阿里云服…

真题详解(DNS)-软件设计(六十三)

真题详解&#xff08;有向图&#xff09;-软件设计&#xff08;六十二)https://blog.csdn.net/ke1ying/article/details/130443040 顺序存储&#xff1a;元素和存储空间相对位置来表示数据元素之间逻辑关系。 RFB&#xff1a;远程访问图形用户界面的简单协议。 在ISO/IEC9126软…

【五一创作】跑alpaca-lora语言模型的常见问题(心得)

训练部署alpaca-lora语言模型常见问题 Alpaca-Lora是一个开源的自然语言处理框架&#xff0c;使用深度学习技术构建了一个端到端的语言模型。在训练和部署alpaca-lora语言模型时&#xff0c;可能会遇到一些常见问题。本文将介绍一些这些问题及其解决方法。 1. bitsandbytes版…

计算机视觉毕业后找不到工作怎么办?怒刷leetcode,还是另寻他路?

文章目录 一、计算机视觉毕业后找不到工作怎么办&#xff1f;二、大环境&#xff1a;前两年的泡沫太大三、还是要把自己的基本功搞扎实&#xff0c;真正的人才什么时候都紧缺四、转换思路&#xff0c;另投他坑五、要有毅力&#xff0c;心态放平六、最后的建议 一、计算机视觉毕…

Python毕业设计之django社区报修维修预约上门服务系统

开发语言&#xff1a;Python 框架&#xff1a;django Python版本&#xff1a;python3.7.7 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm 目 录 摘 要 I Pick to II 1绪论 1 1.1项目研究的背景 1 1.2开发意义 1 1.3项…

「数据架构」介绍下一代主数据管理(MDM)

主数据管理是旨在创建和维护权威、可靠、可持续、准确、及时和安全的环境的过程和技术框架。这个环境代表了一个单一版本的事实&#xff0c;作为跨不同的系统、业务单元和用户社区的可接受的记录系统。 尽管MDM不是新的&#xff0c;但是最近人们对开发MDM解决方案的兴趣大增。这…

正则表达式 Regular Expression

情景引入改代码查找文件词法分析器网站注册密码信息爬取 简介在线测试工具RegulexRegExr 语法普通字符非打印字符特殊字符限定符定位符修饰符元字符 实例匹配邮箱 情景引入 改代码 修改代码格式问题&#xff0c;或者重命名代码里的某个变量等&#xff0c;都可以使用 VS Code …

Mysql 管理

目录 0 课程视频 1 系统数据库 -> 安装完mysql ->自带四个数据库 2 常用工具 -> 写脚本用 2.1 mysql 客户端工具 2.2 mysqladmin 2.3 mysqlbinlog -> 二进制日志 -> 运维讲解 2.4 mysqlshow 2.5 mysqldump 备份用 ->导出 2.6 mysqlimport/source -…

一篇带你了解大厂都在用的DDD领域驱动设计

一、DDD到底是什么 DDD全称Domain Driven Design&#xff0c;领域驱动设计。 为了解决快速变化、复杂系统的设计问题的 领域驱动设计是Eric Evans在2004年发表的Domain Driven Design&#xff08;领域驱动设计&#xff0c;DDD)著作中提出的一种从系统分析到软件建模的一套方…

K8s基础2——部署单Master节点K8s集群、切换containerd容器运行时

文章目录 一、部署K8S集群方式二、kubeadm工具搭建K8s集群2.1 资源配置2.2 服务器规划2.3 搭建流程2.3.1 操作系统初始化2.3.2 使用docker容器引擎2.3.3 安装cri-dockerd2.3.4 安装kubeadm&#xff0c;kubelet和kubectl2.3.5 master节点初始化2.3.6 加入node节点2.3.7 部署容器…

redhat 7.9 安装oracle 11g-11.2.0.4

redhat 7.9 安装oracle 11g-11.2.0.4 1、数据库下载和安装文档1.1、查看oracle 11g 适合安装的linux版本1.2、安装文档1.3、license种类解释&#xff08; XE版 标准本 个人版 企业版&#xff09;1.4、在安装完oracle后再创建数据库1.5、DBA的文档1.6、Automatic Storage Manage…

2.4 等比数列

学习步骤&#xff1a; 如果我要学习等比数列&#xff0c;我会按照以下步骤进行学习&#xff1a; 定义和性质&#xff1a;首先了解等比数列的定义和性质&#xff0c;包括公比、首项、通项公式、求和公式等。 例题练习&#xff1a;通过练习一些简单的例题来理解等比数列的概念和…