一、配置文件
1、引入客户端依赖;
2、配置AppId、apollo-meta
1、引入pom依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.6.0</version>
</dependency>
2、SpringBoot配置文件
# 启用apollo
apollo.bootstrap.enabled = true
# AppId
app.id=fly-demo
# Apollo Meta Server
apollo.meta=http://config-service-url
# 配置项保持和页面上的顺序一致 适用于1.6.0及以上版本
#apollo.property.order.enable=true
# 配置访问秘钥 适用于1.6.0及以上版本
#apollo.accesskey.secret=00ae2d59213847c2bee37fb45848a11a
# 将Apollo配置加载提到初始化日志系统之前(1.2.0+)
#apollo.bootstrap.eagerLoad.enabled=true
二、客户端(系统)使用
Spring Boot集成方式
1、SpringBoot配置(application.properties)
# 启用apollo
apollo.bootstrap.enabled = true
2、配置注入(Spring Placeholder的使用)
2.1、Java Config使用方式
@Configuration
@EnableApolloConfig
public class AppConfig {
@Value("${timeout:100}")
private int timeout;
@Value("${batch:200}")
private int batch;
}
2.2、ConfigurationProperties使用方式
@ConfigurationProperties(prefix = "redis.cache")
public class SampleRedisConfig {
private int expireSeconds;
private int commandTimeout;
public void setExpireSeconds(int expireSeconds) {
this.expireSeconds = expireSeconds;
}
public void setCommandTimeout(int commandTimeout) {
this.commandTimeout = commandTimeout;
}
}
三、自动更新注入的值
@ConfigurationProperties如果需要在Apollo配置变化时自动更新注入的值,需要配合使用EnvironmentChangeEvent或RefreshScope。
参考地址:
1、【推荐】监听Apollo事件(@ApolloConfigChangeListener)
EnvironmentChangeEvent 配合@ApolloConfigChangeListener,使配置变动自动更新注入
@Component
public class ApolloConfigListener implements ApplicationContextAware {
private static final Logger logger = LoggerFactory.getLogger(ApolloConfigListener.class);
private ApplicationContext context;
@ApolloConfigChangeListener
private void onPropertiesChanged(ConfigChangeEvent changeEvent) {
logger.info("apollo config Refreshing");
for (String changedKey : changeEvent.changedKeys()) {
ConfigChange configChange = changeEvent.getChange(changedKey);
String oldValue = configChange.getOldValue();
String newValue = configChange.getNewValue();
logger.info(" changedKey:【{}】,oldValue:【{}】, newValue:【{}】", changedKey, oldValue, newValue);
}
refreshProperties(changeEvent);
logger.info("apollo config refreshed");
}
// update properties for bean,with @ConfigurationProperties
private synchronized void refreshProperties(ConfigChangeEvent configChangeEvent) {
this.context.publishEvent(new EnvironmentChangeEvent(configChangeEvent.changedKeys()));
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
}
2、RefreshScope(@RefreshScope)
配合Spring Cloud的RefreshScope使用,用@ApolloConfigChangeListener,监听配置变动,刷新refreshScope
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
@ConfigurationProperties(prefix = "redis.cache")
// 自动刷新
@RefreshScope
public class SampleRedisConfig {
private int expireSeconds;
private int commandTimeout;
public void setExpireSeconds(int expireSeconds) {
this.expireSeconds = expireSeconds;
}
public void setCommandTimeout(int commandTimeout) {
this.commandTimeout = commandTimeout;
}
}
@ConditionalOnProperty("redis.cache.enabled")
@Component
public class SpringBootApolloRefreshConfig {
private static final Logger logger = LoggerFactory.getLogger(SpringBootApolloRefreshConfig.class);
private final SampleRedisConfig sampleRedisConfig;
private final RefreshScope refreshScope;
public SpringBootApolloRefreshConfig(
final SampleRedisConfig sampleRedisConfig,
final RefreshScope refreshScope) {
this.sampleRedisConfig = sampleRedisConfig;
this.refreshScope = refreshScope;
}
@ApolloConfigChangeListener(value = {ConfigConsts.NAMESPACE_APPLICATION, "TEST1.apollo", "application.yaml"},
interestedKeyPrefixes = {"redis.cache."})
public void onChange(ConfigChangeEvent changeEvent) {
logger.info("before refresh {}", sampleRedisConfig.toString());
refreshScope.refresh("sampleRedisConfig");
logger.info("after refresh {}", sampleRedisConfig.toString());
}
}
3、Apollo单独更新某个值
@ApolloConfigChangeListener
private void someOnChange(ConfigChangeEvent changeEvent) {
//update injected value of batch if it is changed in Apollo
if (changeEvent.isChanged("batch")) {
batch = config.getIntProperty("batch", 100);
}
}
四、测试模式
1、引入pom依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-mockserver</artifactId>
<version>1.6.0</version>
</dependency>
2、测试类
根据官网修改;@SpringApplicationConfiguration 注解在1.4+已被替换为@SpringBootTest
@RunWith(SpringRunner.class)
@SpringBootTest
class ApplicationTests {
private static final String otherNamespace = "application";
@Autowired
private TestBean testBean;
// 启动apollo的mockserver
@ClassRule
public static EmbeddedApollo embeddedApollo = new EmbeddedApollo();
@Test
@DirtiesContext // 这个注解很有必要,因为配置注入会弄脏应用上下文
public void testPropertyInject(){
assertEquals("value1", testBean.key1);
assertEquals("value2", testBean.key2);
}
@Test
@DirtiesContext
public void testListenerTriggeredByAdd() throws InterruptedException, ExecutionException, TimeoutException {
embeddedApollo.addOrModifyProperty(otherNamespace,"someKey","someValue");
ConfigChangeEvent changeEvent = testBean.futureData.get(5000, TimeUnit.MILLISECONDS);
assertEquals(otherNamespace, changeEvent.getNamespace());
assertEquals("someValue", changeEvent.getChange("someKey").getNewValue());
}
@EnableApolloConfig("application")
@Configuration
static class TestConfiguration{
@Bean
public TestBean testBean(){
return new TestBean();
}
}
static class TestBean{
@Value("${key1:default}")
String key1;
@Value("${key2:default}")
String key2;
SettableFuture<ConfigChangeEvent> futureData = SettableFuture.create();
@ApolloConfigChangeListener("application")
private void onChange(ConfigChangeEvent changeEvent) {
futureData.set(changeEvent);
}
}
}