springboot + 攜程apllo 配置實時生效(1)-指定生效
springboot + 攜程apllo 配置實時生效(2)-全局生效
前兩天寫了一篇博客,springboot + 攜程apollo ,實現修改apollo 配置實時生效,當時寫的生效,只是針對某一bean的scope 中的配置從ApolloConfig 中獲取更新的值有效,對於其他註解@Value的 Bena Scope 是不能實時生效的,基於Apollo官方文檔,要想全局生效,需要使用RefreshScoup.refreshAll(), 把ApolloConfig 中最新的值,更新到有@RefresScope 註釋的Bean 中,於是又研究了一番,終於驗證成功。
1、RefreshScoup 是需要依賴springcloud的,我們springboot項目中,是沒有引入springcloud,所以需要針對刷新功能引入相關依賴。
<!--監控+refresh配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>1.4.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.8.RELEASE</version>
</dependency>
有一點需要注意,我們的項目,公司封裝的springboot 版本還是在2.0以下,以上引入的依賴spring-cloud-starter-config和spring-boot-starter-actuator 版本如果是2.0以上,啓動後會報異常,提示:
ClasspathLoggingApplicationListener pplication failed to start with classpath
搜索了一些資料,說是application.properties中的配置有不對的,但是排查了一圈,也沒發現問題所在,最終發現是springBoot 版本和 springcloud版本不兼容導致的。
具體版本兼容可以參看:
spring boot 與spring cloud版本不匹配導致的NoSuchMethodError問題
於是把spring-cloud-starter-config和spring-boot-starter-actuator 版本改爲1.x ,最終異常解決。
2、在application.properties中添加配置
management.endpoints.web.exposure.include=*
management.endpoints.enabled-by-default=true
3、啓動項,添加@EnableApolloConfig
4、配置apollo的監聽
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class ApolloConfigChanged implements ApplicationContextAware {
ApplicationContext applicationContext;
@Autowired
RefreshScope refreshScope;
//這裏指定Apollo的namespace,非常重要,如果不指定,默認只使用application
@ApolloConfigChangeListener(value = {ConfigConsts.NAMESPACE_APPLICATION})
public void onChange(ConfigChangeEvent changeEvent) {
for (String changedKey : changeEvent.changedKeys()) {
log.info("apollo changed namespace:{} Key:{} value:{}", changeEvent.getNamespace(), changedKey, changeEvent.getChange(changedKey));
}
refreshProperties(changeEvent);
}
public void refreshProperties(ConfigChangeEvent changeEvent) {
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
refreshScope.refreshAll();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
5、apollo 配置讀取的Bean 對象和 在其他bean 中注入@Value 使用
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
@Data
@RefreshScope
@Service
public class TestJavaConfigBean {
@Value("${cutiyu.test}")
private String test;
}
@RestController
@RequestMapping("/")
@Slf4j
@RefreshScope
public class HelloController {
@Value("${cutiyu.test}")
private String test;
@Autowired
TestJavaConfigBean testJavaConfigBean;
@RequestMapping("/hello")
public String hello() {
String test12 = testJavaConfigBean.getTest();
System.out.println(this.test);
System.out.println(test12);
return "Hello";
}
6、啓動項目,更改apollo 配置,併發布後, 可以看到獲取的值是能夠實時更新的
特別說明:
有些文檔,可能是基於springboot + springcloud config 的一些集成,說是全局刷新配置,需要手動刷新,不同的springboot 版本,執行的接口不一樣,實測後,結果都是404 ,但是不影響上面的實時生效,特別記錄一下。猜測原因,是上面的配置,並不是完整的應用spring cloud 的config 功能,依賴的jar 可能是不完整的,所以相應的刷新接口不存在,而報404錯誤。
localhost:8080/refresh
localhost:8080/actuator/refresh
localhost:8080/actuator/bus/refresh