springboot + 攜程apllo 配置實時生效(2)-全局生效

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章