1.前言
因为某些原因,有些项目没有使用nacos作为配置中心。但是有些配置有可能是动态变化的,如果通过springboot的配置文件,每次修改配置就需要重启项目,有些麻烦。如果采用外部读取文件的方式,频繁的io也划不来。所以可以借助Commons-Configuration2来实现配置的动态加载。
2.Commons Configuration 简介
Commons Configuration软件库提供了一个通用的配置接口,它使 一个 Java 应用程序,用于从各种来源读取配置数据。
共享资源配置 提供对单个和多值配置参数的类型化访问,可以支持多种配置文件格式:
- Properties files
- XML documents
- Windows INI files
- Property list files(plist)
- JNDI
- JDBC Datasource
- System properties
- Applet parameters
- Servlet parameters
3.使用Commons-Configuration2
(1)导入Commons-Configuration2依赖
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-configuration2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-configuration2</artifactId>
<version>2.8.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
(2)编写工具类
MyConfigManager .class
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
/**
* 配置管理器类,用于加载和管理配置信息。
*/
public class MyConfigManager {
/**
* 配置文件路径常量。
* 注意:这里的路径应该是相对于项目根目录的路径,或者是绝对路径。
*/
private static final String CONFIG_PATH = "E:\\mytest.properties";
/**
* 配置信息对象,使用PropertiesConfiguration类型。
*/
private PropertiesConfiguration config;
/**
* 配置信息的缓存,使用ConcurrentHashMap来保证线程安全。
*/
private ConcurrentHashMap<String, String> configMap = new ConcurrentHashMap<>();
/**
* 日志记录器,用于记录配置管理器的操作日志。
*/
private static final Logger LOGGER = Logger.getLogger(MyConfigManager.class.getName()); // 创建日志记录器
/**
* ConfigManager的构造函数,初始化配置管理器。
*
* @throws Exception 如果加载配置文件失败,则抛出异常。
*/
public MyConfigManager() throws Exception {
loadConfig();
}
/**
* 加载配置文件的方法。
*
* @throws Exception 如果读取或解析配置文件失败,则抛出异常。
*/
private void loadConfig() throws Exception {
// 记录加载配置文件的日志
LOGGER.info("加载http.properties配置文件: " + CONFIG_PATH);
config = new Configurations().properties(new File(CONFIG_PATH));
// 遍历配置文件中的所有键值对,并存入configMap中
for (Iterator<String> keys = config.getKeys(); keys.hasNext(); ) {
String key = keys.next();
configMap.put(key, config.getString(key));
}
}
/**
* 重置配置项的方法。
*
* @param key 配置项的键。
* @param newValue 配置项的新值。
* @throws Exception 如果读写配置文件失败,则抛出异常。
*/
public void updateKeyConfig(String key, String newValue) throws Exception {
// 创建Properties对象,用于读写配置文件
Properties properties = new Properties();
try (FileInputStream in = new FileInputStream(CONFIG_PATH)) {
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
}
// 设置配置项的新值
properties.setProperty(key, newValue);
// 将修改后的配置项写回配置文件
try (FileOutputStream out = new FileOutputStream(CONFIG_PATH)) {
properties.store(out, "Updated properties file");
} catch (IOException e) {
e.printStackTrace();
}
// 重新加载配置文件,更新configMap
loadConfig();
// 记录重置配置文件的日志
LOGGER.info("重置http.properties配置文件:" + CONFIG_PATH);
}
/**
* 重置加载配置项的方法。
*
* @throws Exception 如果读写配置文件失败,则抛出异常。
*/
public void resetConfig() throws Exception {
// 重新加载配置文件,更新configMap
loadConfig();
// 记录重置配置文件的日志
LOGGER.info("重置http.properties配置文件:" + CONFIG_PATH);
}
/**
* 获取配置项的值。
*
* @param key 配置项的键。
* @return 配置项的值,如果找不到则返回null。
*/
public String getProperty(String key) {
// 从configMap中获取配置项的值
return configMap.get(key);
}
}
ConfigManagerUtil.class
/**
* 配置管理器工具类,用于初始化、获取、更新和重置配置。
*/
public class ConfigManagerUtil {
// 配置管理器的单例实例
private static MyConfigManager myConfigManager;
/**
* 构造函数,私有化以防止外部实例化。
*/
public ConfigManagerUtil() {
}
/**
* 初始化配置管理器。如果配置管理器尚未初始化,则创建一个新的实例。
*
* @throws Exception 如果初始化过程中出现错误,则抛出异常。
*/
public static void init() throws Exception {
if (myConfigManager == null) {
myConfigManager = new MyConfigManager();
}
}
/**
* 根据键获取配置属性值。
*
* @param key 配置项的键。
* @return 配置项的值。
* @throws Exception 如果获取过程中出现错误,则抛出异常。
*/
public static String getProperty(String key) throws Exception {
init();
return myConfigManager.getProperty(key);
}
/**
* 更新指定配置键的值。
*
* @param key 配置项的键。
* @param newValue 新的配置值。
* @throws Exception 如果更新过程中出现错误,则抛出异常。
*/
public static void updateKeyConfig(String key, String newValue) throws Exception {
myConfigManager.updateKeyConfig(key, newValue);
}
/**
* 重置配置到初始状态。
*
* @throws Exception 如果重置过程中出现错误,则抛出异常。
*/
public static void resetConfig() throws Exception {
myConfigManager.resetConfig();
}
}
4.测试
(1)创建测试controller。MyTestController.class
@RestController
@RequestMapping("/handleDingTalk/test")
@Slf4j
public class MyTestController {
@GetMapping("getProperty")
public CommonResult getProperty(String key) {
try {
String property = ConfigManagerUtil.getProperty(key);
log.info(property);
return CommonResult.success(property);
} catch (Exception e) {
log.info(e.getMessage());
return CommonResult.failed(e.getMessage());
}
}
@GetMapping("updateKeyConfig")
public CommonResult updateKeyConfig(String key, String newValue) {
try {
ConfigManagerUtil.updateKeyConfig(key, newValue);
return CommonResult.success("success");
} catch (Exception e) {
log.info(e.getMessage());
return CommonResult.failed(e.getMessage());
}
}
@GetMapping("resetConfig")
public CommonResult resetConfig() {
try {
ConfigManagerUtil.resetConfig();
return CommonResult.success("success");
} catch (Exception e) {
log.info(e.getMessage());
return CommonResult.failed(e.getMessage());
}
}
}
(2)在E盘下创建一个mytest.properties文件,内容如下
(3)测试获取key
第一次获取testey
第二次获取authKey
日志
结论:通过看日志,可以看出,确实是第一次是加载了配置配置文件,之后再获取的key不在重复加载配置文件。
(4)重置key的值
重置testKey
查看配置文件
调用接口
查看日志
结论,通过接口重置key的值,配置文件中的内容也发生了改变。