准备工作
环境要求
Java 1.8+
Guava 20.0+
必选设置
导入依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.8.0</version>
</dependency>
客户端使用
1、API 方式
API 方式是最简单、高效使用使用 Apollo 配置的方式,不依赖 Spring 框架即可使用。
获取命名空间的配置
// 1、获取默认的命名空间的配置
Config config = ConfigService.getAppConfig();
// 2、获取properties格式的命名空间的配置
// String somePublicNamespace = "CAT";
// Config config = ConfigService.getConfig(somePublicNamespace);
// 3、获取yaml/yml格式的命名空间的配置
// Config config = ConfigService.getConfig("application.yml");
// 4、获取其它格式的命名空间的配置
// ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML);
// String content = configFile.getContent();
String someKey = "someKeyFromDefaultNamespace";
String someDefaultValue = "someDefaultValueForTheKey";
String value = config.getProperty(someKey, someDefaultValue);
通过 Config 的 getProperty 方法可以获取到指定属性对应的属性值。
监听配置变化事件
Config config = ConfigService.getAppConfig();
config.addChangeListener(new ConfigChangeListener() {
@Override
pubic void onChange(ConfigChangeEvent changeEvent) {
System.out.println("Changes for namespace " + changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.println(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()));
}
}
});
希望配置发生变化时得到通知。通过 Config 的 addChangeListener 方法添加一个 ConfigChangeListener 监听器。
2、Spring 整合方式
可以在代码中直接使用,如:@Value("${someKeyFromApollo:someDefaultValue}")
。
也可以在配置文件中使用,如:spring.datasource.url:${someKeyFromApollo:someDefaultValue}
。
甚至可以直接托管 Spring 中的配置。如:在 Apollo 中直接配置 spring.datasource.url=jdbc:mysql://localhost:3306/somedb
。
支持 Spring Boot 的 @ConfigurationProperties
方式。
也支持结合 API 方式使用,如:@ApolloConfig private Config config;
。
2.1 配置
2.1.1 基于 Spring 的配置
注入默认的命名空间的配置到 Spring 中
@Configuration
@EnableApolloConfig
public class AppConfig {
}
注入多个命名空间的配置到 Spring 中
@Configuration
@EnableApolloConfig({"FX.apollo", "application.yml"})
public class AnotherAppConfig {
}
注入多个命名空间的配置到 Spring 中,并且指定顺序
在 @EnableApolloConfig 注解中的 order 属性指定顺序,值越小则顺序越靠前。
@Configuration
@EnableApolloConfig(order = 2)
public class AppConfig {
}
@Configuration
@EnableApolloConfig(value = {"FX.apollo", "application.yml"}, order = 1)
public class AnotherAppConfig {
}
2.1.2 基于 Spring Boot 的配置
额外支持通过 application.properties / bootstrap.properties 进行配置,该方式可以使配置在更早的阶段注入,比如使用 @ConditionalOnProperty
的场景或者有一些 spring-boot-starter 在启动阶段就需要读取配置然后做一些事情。
# 启动阶段注入application命名空间的配置
apollo.bootstrap.enabled = true
也支持注入多个命名空间的配置。
# 启动阶段注入application,FX.apollo,application.yml命名空间的配置
apollo.bootstrap.enabled = true
apollo.bootstrap.namespaces = application,FX.apollo,application.yml
可以让 Apollo 的加载顺序在日志系统之前,比如希望把日志相关的配置(logging.level.root=info
或者 logback-spring.xml 中的参数)也交给 Apollo 管理。
# 启动阶段注入application命名空间的配置
apollo.bootstrap.enabled = true
# 让 Apollo 的加载顺序在日志系统之前
apollo.bootstrap.eagerLoad.enabled = true
2.1.3 基于 Spring Boot Config Data Loader 的配置
详细内容参考官方文档 - Spring Boot Config Data Loader
2.2 使用
2.2.1 Spring Placeholder 的使用
在 Spring 环境中,可以使用占位符的形式注入配置,如:${someKey:someDefaultValue}
。
建议在实际使用时尽量给出默认值,以免由于 key 没有定义导致运行时错误。
从 v0.10.0 版本开始,支持占位符的运行时自动更新。想要关闭占位符的运行时自动更新,可以选择如下任意方法:
1、通过设置系统参数,如启动时传入 -Dapollo.autoUpdateInjectedSpringProperties=false
。
2、通过设置 META-INF/app.properties 中的 apollo.autoUpdateInjectedSpringProperties
属性,如:
app.id = SampleApp
apollo.autoUpdateInjectedSpringProperties = false
2.2.1.1 XML 中占位符的使用
假设 TestXmlBean 中有两个配置项需要注入。
public class TestXmlBean {
private int timeout;
private int batch;
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public void setBatch(int batch) {
this.batch = batch;
}
public int getTimeout() {
return timeout;
}
public int getBatch() {
return batch;
}
}
在 xml 中使用如下方式进行定义。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:apollo="http://www.ctrip.com/schema/apollo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd">
<apollo:config/>
<bean class="com.ctrip.framework.apollo.spring.TestXmlBean">
<property name="timeout" value="${timeout:100}"/>
<property name="batch" value="${batch:200}"/>
</bean>
</beans>
2.2.1.2 Java Config 中占位符的使用
假设 TestJavaConfigBean 中,需要注入两个属性。
public class TestJavaConfigBean {
@Value("${timeout:100}")
private int timeout;
private int batch;
@Value("${batch:200}")
public void setBatch(int batch) {
this.batch = batch;
}
public int getTimeout() {
return timeout;
}
public int getBatch() {
return batch;
}
}
@Configuration
@EnableApolloConfig
public class AppConfig {
@Bean
public TestJavaConfigBean javaConfigBean() {
return new TestJavaConfigBean();
}
}
2.2.2 ConfigurationProperties 的使用
Spring Boot 提供了 @ConfigurationProperties 注解用于将配置注入到 bean 对象中。
Apollo 也支持这种方式。
@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;
}
}
@Configuration
@EnableApolloConfig
public class AppConfig {
@Bean
public SampleRedisConfig sampleRedisConfig() {
return new SampleRedisConfig();
}
}
需要注意的是,@ConfigurationProperties
如果需要在配置发生变化时自动更新注入的值,需要配合使用 EnvironmentChangeEvent 或者 RefreshScope,可以参考 EnvironmentChangeEvent 样例、RefreshScope 样例1、RefreshScope 样例2。
2.2.3 Spring Annotation 的使用
Apollo 在 Spring 环境中,提供了如下三个注解:
@ApolloConfig
:用来自动注入 Config 对象。@ApolloConfigChangeListener
:用来自动注册 ConfigChangeListener。@ApolloJsonValue
:用来将配置的 json 字符串自动注入为对象。
public class TestApolloAnnotationBean {
@ApolloConfig
private Config config; // 注入“application”命名空间的配置
@ApolloConfig("application")
private Config anotherConfig; // 注入“application”命名空间的配置
@ApolloConfig("FX.apollo")
private Config yetAnotherConfig; // 注入“FX.apollo”命名空间的配置
@ApolloConfig("application.yml")
private Config ymlConfig; // 注入“application.yml”命名空间的配置
/**
* jsonBeanProperty=[{"someString":"hello","someInt":100},{"someString":"world!","someInt":200}]
*/
@ApolloJsonValue("${jsonBeanProperty:[]}")
private List<JsonBean> anotherJsonBeans; // 将“jsonBeanProperty”字符串解析并注入
@Value("${batch:100}")
private int batch;
@ApolloConfigChangeListener
public void someOnChange(ConfigChangeEvent changeEvent) { // 监听“application”命名空间的配置的变化
if (changeEvent.isChanged("batch")) {
this.batch = config.getIntProperty("batch", 100);
}
}
@ApolloConfigChangeListener({"application", "FX.apollo", "application.yml"})
public void yetAnotherOnChange(ConfigChangeEvent changeEvent) { // 监听“application”、“FX.apollo”、“application.yml”命名空间的配置的变化
}
}
@Configuration
@EnableApolloConfig
public class AppConfig {
@Bean
public TestApolloAnnotationBean testApolloAnnotationBean() {
return new TestApolloAnnotationBean();
}
}
2.2.4 已有配置迁移
详细内容参考官方文档 - 已有配置迁移