很多配置中心都有一个功能就是:配置中心修改配置以后,业务系统不用重新启动,就可以更新到最新的配置信息,通常的做法是业务系统提供刷新接口,比如spring cloud config 就是客户端内置了更新接口(重启了整个spring容器)。另一个做法是业务系统轮询配置中心,比如appollo,这样肯定会有性能问题。EasyConf采用业调用业务端刷新接口的方法,那个这个接口怎么实现呢。下面把代码贴出来
@RestController
@RequestMapping("/_easyconf")
public class ConfigCenterRefreshController {
@Autowired
private AbstractEnvironment environment;
/**
* runningship
* 从配置中心读取最新配置,并更新所有@Value注解的标注的字段值,不支持ConfigurationProperties的方式
*/
@ResponseBody
@RequestMapping(value = "/refresh")
public String refresh() {
PropertySource<?> target = null;
String configLocation = environment.getProperty("spring.config.location");
if(!StringUtils.isEmpty(configLocation)) {
for(PropertySource<?> ps : environment.getPropertySources()) {
if(ps.getName().startsWith("applicationConfig") && StringUtils.startsWithIgnoreCase(configLocation, "http")) {
target = ps;
break;
}
}
}
if(target ==null) {
return "--spring.config.location没有配置,或者不是一个url地址,你可能没有使用配置中心,没有配置可以刷新";
}
Properties pros = new Properties();
try {
PropertiesLoaderUtils.fillProperties(pros, new UrlResource(configLocation));
} catch (IOException e) {
e.printStackTrace();
return "reload failed , "+e.getMessage();
}
// 更新到spring容器
Map map = (Map) target.getSource();
map.clear();
map.putAll(pros);
//更新所有bean @value注解的字段。
for(String beanName : ApplicationContextHolder.getContext().getBeanDefinitionNames()) {
Object bean = ApplicationContextHolder.getContext().getBean(beanName);
for(Field f : bean.getClass().getDeclaredFields()) {
Value valueAnno = f.getAnnotation(Value.class);
if(valueAnno==null) {
continue;
}
String key = valueAnno.value();
if(key==null) {
continue;
}
key = key.replace("${", "").replace("}", "");
key = key.split(":")[0];
if(map.containsKey(key)) {
f.setAccessible(true);
try {
f.set(bean, map.get(key));
} catch (Exception e) {
return e.getMessage();
}
}
}
}
return "all @Value field update success";
}
ApplicationContextHolder
@Component
public class ApplicationContextHolder implements ApplicationContextAware{
private static ApplicationContext context = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static ApplicationContext getContext() {
return context;
}
}