背景
1.项目中关于数据库密码等信息想要进行加密处理,所以引入了jasypt-spring-boot-starter,版本3.0.3
2.后来项目接入了apollo的动态配置中心,apollo-client-config-data版本1.9.1
3.此时发现@Value的值,不能进行动态刷新,当发布新配置时,apollo会进行更新操作,可是程序里仍旧是旧值
4.通过查看文件,可以看到本地拉下来的配置文件中,值已经同步成和apollo配置中心一样。
原因
这块我理解的还不够透彻,大家可以看一下apollo的这个issues,等我研究明白了我再写,先看这个吧
apollo跟jasypt-spring-boot-2.1.0.jar不兼容
解决方案
方案一
高版本jasypt会有这个问题,其他博客说1.18/1.16版本可以用,应该是2.0.0以下的都可以,我尝试没成功,大家也可以参考一下。
方案二
照着issues里的方案整了一版,但是不太稳定,还没搞明白为啥,但是能用,直接上代码:
@Order(-12312931) public class ApolloConfigChangeListener implements ConfigChangeListener { public ApolloConfigChangeListener() { } @Override public void onChange(ConfigChangeEvent changeEvent) { changeEvent.changedKeys().forEach(k -> { this.refresh(); }); } public void refresh() { refreshCachedProperties(); } private void refreshCachedProperties() { ConfigurableApplicationContext context = (ConfigurableApplicationContext) SpringContextUtil.getApplicationContext(); PropertySources propertySources = context.getEnvironment().getPropertySources(); propertySources.forEach(this::refreshPropertySource); } @SuppressWarnings("rawtypes") private void refreshPropertySource(PropertySource<?> propertySource) { if (propertySource instanceof CompositePropertySource) { CompositePropertySource cps = (CompositePropertySource) propertySource; cps.getPropertySources().forEach(this::refreshPropertySource); } else if (propertySource instanceof EncryptablePropertySource) { EncryptablePropertySource eps = (EncryptablePropertySource) propertySource; eps.refresh(); } } }
为此还写了个工具类:
public class SpringContextUtil { private static ApplicationContext applicationContext; //获取上下文 public static ApplicationContext getApplicationContext() { return applicationContext; } //设置上下文 public static void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtil.applicationContext = applicationContext; } //通过名字获取上下文中的bean public static Object getBean(String name){ return applicationContext.getBean(name); } //通过类型获取上下文中的bean public static Object getBean(Class<?> requiredType){ return applicationContext.getBean(requiredType); } }
然后启动类也要做修改,修改main方法:
public static void main(String[] args) { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); ApplicationContext context = SpringApplication.run(BmsWebApplication.class, args); SpringContextUtil.setApplicationContext(context); //这里application.yml是我要关注的apollo里面的那个配置文件 ConfigService.getConfig("application.yml") .addChangeListener(new ApolloConfigChangeListener()); }
总结
经过以上修改,配置是能实时更新的,可是不太稳定,偶尔会出现值没更新的情况,此时多改几次就可以了,我还没搞清楚为什么,希望有比较懂的大神评论告诉我,感谢