背景
加载自定义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 -->
解析工具类
- 工具类实现InitializingBean接口的afterPropertiesSet的方法,这样可以在spring容器实例化工具类后,自动执行afterPropertiesSet方法,实现加载配置文件的代码
- properites文件目录,通过@Value注入,支持“*.properite”通配方式,多个目录用半角“,”隔开
- 多个properties文件要防止key重复,建议根据properties文件内容,在key上加前缀,例如,配置sftp信息,key就加“sftp.xxxx”。配置socket信息,key就加“sokcet.xxxx”。
- @Lazy注解,在使用的时候才实例化。可以减少应用启动时的工作量,提高启动速度。
- 代码实现
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秒。在这个暂停时间内修改配置文件,再取值就是更新后的值。如果没取到新值,可能是改的慢了,可以让暂停时间长一些。还有修改完了一定要保存,否则没效果。