最近项目中较多地方使用了类似Util.staticUrl的静态地址字段,需要改造为从配置中心或数据库获取值,因此用到了@RerefreshScope注解。
- 从配置中心取值
@Data
@Slf4j
@Component
@RefreshScope
@Scope("prototype")
public class InterfaceConfig implements InitializingBean {
@Value("${platform.hx.url}")
private String hxUrl;
- 从数据库取值
@Slf4j
@Component
public class ApplicationConfig implements ApplicationListener<ApplicationReadyEvent> {
@Autowired IBaseClient iBaseClient;
@Autowired InterfaceConfig interfaceConfig;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
interfaceConfig.getHxUrl(); //强制InterfaceConfig初始化一次,以便从nacos获取配置并生效
Map<String, String> map = iBaseClient.getBaseInfoMap("type");
String hxUrl = map.get("hxUrl");
Util.updateUrl(hxUrl);
}
}
ApplicationListener<ApplicationReadyEvent> 在应用启动完成时执行,尝试从数据库获取配置,无对应配置时不更改地址。
public static void updateUrl(String hxUrl) {
if(StringUtil.isBlank(hxUrl)) {
log.info("hx.url is blank, keep old url: {}", Util.HX_Url);
}else if(Objects.equal(hxUrl, StatusInfoUtil.HX_Url)) {
log.info("hx.url not change, keep old url: {}", StatusInfoUtil.HX_REQ_Url);
}else {
log.info("update hx.url from:{} to:{}", Util.HX_Url, hxUrl);
StatusInfoUtil.HX_Url = hxUrl;
}
} - 手动更新配置
@ApiOperation(value = "更新服务地址" ,httpMethod = "GET")
@GetMapping(value = "/web/updateInterfaceConfig", produces = "application/json;charset=UTF-8")
public ResponseResult<JSONObject> updateInterfaceConfig(String hxUrl){
JSONObject json = new JSONObject();
json.put("hxUrlOld", Util.HX_Url);
if(StringUtils.isAllBlank(hxUrl, lpUrl)) {
Map<String, String> map = iBaseClient.getBaseInfoMap("type");
hxUrl = map.get("hxUrl");
}
Util.updateUrl(hxUrl);
json.put("hxUrl", Util.HX_Url);
return json;
}
有时需要更灵活地变更配置,curl提供hxUrl值时可以立即生效,不提供值时可以再次从数据库取值。
@Override
public void afterPropertiesSet() throws Exception {
Util.updateUrl(hxUrl);
}
@EventListener
public void eventListener(EnvironmentChangeEvent event) throws Exception {
log.info("config change keys: {}", event.getKeys());
}
}
@RefreshScope正确的使用方式是在代码中注入InterfaceConfig实例,每次通过getHxUrl()取值。但是项目中较多地方使用了Util.hxUrl,因此需要在nacos配置更新时同步此值。由于项目中没有注入InterfaceConfig实例,也没有调用其getHxUrl方法,因此使用@EventListener监听nacos配置更新,但是此时hxUrl还没有拿到更新后的值,因此不能直接调用Util.updateUrl。@Scope(“prototype”)配合监听事件,会导致InterfaceConfig重新初始化,从而再次调用afterPropertiesSet更新配置。