springboot项目刷新配置

很多配置中心都有一个功能就是:配置中心修改配置以后,业务系统不用重新启动,就可以更新到最新的配置信息,通常的做法是业务系统提供刷新接口,比如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;
    }
}

你可能感兴趣的:(springboot项目刷新配置)