Java 加载并实时刷新多个自定义的Properties配置文件

背景

  加载自定义properites配置文件有很多方法,但是大部分都不可以实时刷新配置文件。下面介绍一种基于netflix的方法,它可以很方便的加载配置文件,支持取各种类型值的方法,同时也支持实时刷新修改过的配置文件。
  工程是基于springboot的,导入springboot依赖就不单独写出了。

maven依赖

 		<!-- 用于加载多个proerties文件,可自动更新配置 -->
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.5.18</version>
            <exclusions>
                <exclusion>
                    <groupId>com.netflix.archaius</groupId>
                    <artifactId>archaius-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.netflix.archaius</groupId>
            <artifactId>archaius-core</artifactId>
            <version>0.7.7</version>
        </dependency>
        <dependency>
            <groupId>commons-configuration</groupId>
            <artifactId>commons-configuration</artifactId>
            <version>1.6</version>
        </dependency>
        <!-- 用于加载proerties文件,可自动更新配置 #end -->

解析工具类

  1. 工具类实现InitializingBean接口的afterPropertiesSet的方法,这样可以在spring容器实例化工具类后,自动执行afterPropertiesSet方法,实现加载配置文件的代码
  2. properites文件目录,通过@Value注入,支持“*.properite”通配方式,多个目录用半角“,”隔开
  3. 多个properties文件要防止key重复,建议根据properties文件内容,在key上加前缀,例如,配置sftp信息,key就加“sftp.xxxx”。配置socket信息,key就加“sokcet.xxxx”。
  4. @Lazy注解,在使用的时候才实例化。可以减少应用启动时的工作量,提高启动速度。
  5. 代码实现
package com.ylink.cfcust.core.config.jackson1;

import com.netflix.config.*;
import com.netflix.config.sources.URLConfigurationSource;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;

import java.io.IOException;


/**
 * @create 2024/1/29 10:08
 */
@Component
@Lazy   //延时加载,到使用的时候才实例化。可以检查启动时的工作量,提高启动速度。
public class JsonkeyProperties implements InitializingBean {

    //多个目录用","隔开
    @Value("${jackson.json-keys.path:file:./config/jsonkeys/*.properties}")
    private String configFilePath;

    @Override
    public void afterPropertiesSet() throws Exception {

        if(this.configFilePath.contains(",")){
            String[] filePathArray = this.configFilePath.split(",");
            for (String fPath: filePathArray){
                handlConfigPath(fPath);
            }
        }else {
            handlConfigPath(this.configFilePath);
        }


    }

    private void handlConfigPath(String configFilePath) throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources(configFilePath);

        if(ArrayUtils.isNotEmpty(resources)){
            for(Resource resource : resources){
                PolledConfigurationSource source = new URLConfigurationSource(resource.getURL());
                //
                DynamicConfiguration configuration = new DynamicConfiguration(source,
                        //每10秒自动刷新配置
                        new FixedDelayPollingScheduler(0, 10000, true)
                );
                ConfigurationManager.loadPropertiesFromConfiguration(configuration);
            }
        }
    }

    /**
     * 这里传入className, fieldName,是我自己的功能需要
     * 普通情况直接传入key就可以了
     * 像这样:getStringProperty(String key, String defaultValue)
     *
     * @param className
     * @param fieldName
     * @return
     */
    public String getStringProperty(String className, String fieldName){
        String key = className + "." + fieldName;
        return DynamicPropertyFactory.getInstance().getStringProperty(key,fieldName).get();
    }

    public Integer getIntegerProperty(String className, String fieldName){
        String key = className + "." + fieldName;
        return DynamicPropertyFactory.getInstance().getIntProperty(key,0).get();
    }

    //DynamicPropertyFactory.getInstance()可以取各种类型的值,比如Boolean,Double等。可以根据需要实现

    /**
     * 根据默认值类型,确定返回值类型
     * @param key
     * @param defaultValue
     * @param <T>
     * @return
     */
    public <T> T getContextualProperty(String key, T defaultValue){
        return DynamicPropertyFactory.getInstance().getContextualProperty(key,defaultValue).getValue();
    }

}

测试

  • 测试代码
	//注入工具类
	@Autowired
    private JsonkeyProperties jsonkeyProperties;

 	public void test1() throws IOException {
        String value = this.jsonkeyProperties.getStringProperty("UserInfo", "userName");
        System.out.println("原始值 confivalue -> " + value);

        String startTime = new Timestamp(System.currentTimeMillis()).toString();
        System.out.println(startTime + " -> 开始暂停30秒");
        try {
            Thread.sleep(30000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String endTime = new Timestamp(System.currentTimeMillis()).toString();
        System.out.println(endTime + " -> 结束暂停");
        String value1 = this.jsonkeyProperties.getStringProperty("UserInfo", "userName");
        System.out.println("更新后的 confivalue -> " + value1);
    }
  • 测试配置文件
    配置文件

  • 测试结果
      因为刷新时间是10秒,所以在测试代码中,暂停了30秒。在这个暂停时间内修改配置文件,再取值就是更新后的值。如果没取到新值,可能是改的慢了,可以让暂停时间长一些。还有修改完了一定要保存,否则没效果。测试结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值