配置文件的动态加载

       我们的代码为了重用或是项目为了更好地适应运营的变化,总免不了要使用配置文件,但有些项目需要24小时运营,不能为了修改配置而停机重启,所以配置文件的动态加载就显得较为重要,下面要介绍的就是commons项目的动态加载配置文件的机制,及项目中如何利用利用commons来实现配置的动态加载。

      先介绍项目源码地址: http://git.oschina.net/rjzjh/commons,maven中央库引用:

<dependency>

<groupId>net.wicp.tams</groupId>

<artifactId>commons</artifactId>

<version>0.1.5</version>

</dependency>

commons包会读classpath根目录下的commonsUtil.properties配置文件,如果该目录下没有找到该文件,那么commons包会读取jar包中的commonsUtil.properties配置文件来做为该包的配置文件:

                                                     212902_Gf23_1865914.png

所有的配置,配置文件的热加载由net.wicp.tams.commons.Conf来完,Conf由TimerTask来完成Job工作,它会一分钟执行一次配置文件的比较工作,如果扫描的配置文件的修改时间大于已加载的配置文件的修改时间,则会启动各模块的的回调工作

if (curmodified > lastModified) {
						lastModified = curmodified;
						Properties oldProperties = (Properties) utilProperties.clone();// 旧配置属性
						Properties newProperties = new Properties();
						fileInputStream = new FileInputStream(file);
						newProperties.load(fileInputStream);
						// 重新装配新的属性
						utilProperties.clear();
						for (Object key : newProperties.keySet()) {
							utilProperties.put(key, newProperties.get(key));
						}
						for (String moudle : reshBacks.keySet()) {
							String[] propNames = props.get(moudle);
							if (ArrayUtils.isEmpty(propNames)) {// 没有观察的属性名称不做调用
								continue;
							}
							// 查找是否观察的属性有变化
							boolean ischange = false;
							for (String propName : propNames) {
								if (propName.endsWith("%s")) {// 取多个属性值,如redisserver%s
									String keyPre = propName.substring(0, propName.length() - 2);
									Map<String, String> oldmap = CollectionUtil.getPropsByKeypre(oldProperties, keyPre);
									Map<String, String> newmap = CollectionUtil.getPropsByKeypre(newProperties, keyPre);
									for (String key : oldmap.keySet()) {
										String oldValue = oldmap.get(key);
										String newValue = newmap.get(key);
										if (!StringUtil.hasNull(oldValue).equals(StringUtil.hasNull(newValue))) {
											ischange = true;
											break;
										}

									}
									if (ischange) {
										break;
									}
								} else {
									String oldValue = oldProperties.getProperty(propName);
									String newValue = newProperties.getProperty(propName);
									if (!StringUtil.hasNull(oldValue).equals(StringUtil.hasNull(newValue))) {
										ischange = true;
										break;
									}
								}

							}
							if (ischange) {
								try {
									reshBacks.get(moudle).doReshConf(utilProperties);// 也是新的Properties
								} catch (Exception e) {
									logger.error("加载配置文件失败,回调模块[" + moudle + "]错误", e);
								}
							}
						}
						logger.info("成功刷新配置文件");
					}


其中   reshBacks  就是各模块的回调函数,看RedisClient的工具类:

Conf.addCallBack("redis", new Callback() {
			@Override
			public void doReshConf(Properties newProperties) {
				RedisClient.setInitPool(true);// Redis动态刷新
			}
		}, "redisserver%s");

redis指的是模块名,第二个参数是回调函数,第三个参数是指该模块所关心的配置项,如果commonsUtil.properties文件中以redisserver开始的属性项有改动,则会触发第二个参数的的回调对象,RedisClient.setInitPool(true);会重新跟据新的配置属性来初始化redis连接池。

          commons包中所有的模块的属性动态加载都是用上述一样的机制,如果项目中也需要动态加载,可以在在classpath的目录下的commonsUtil.properties文件配置好自己的属性配置项,然后在适当的时间(如类加载的时候或是单例时对象实例化时候),通过Conf.addCallBack方法加入回调对象(实现net.wicp.tams.commons.Conf.Callback接口),就可以完成配置文件的热加载。如果没有要初始化或是要析构的东西可以不用加入回调对象,直接通过Conf.get方法拿到所配置的配置项值就好了。



转载于:https://my.oschina.net/rjzjh/blog/536665

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值