配置中心是大部分服务的强需求。自己运维一套会各种踩坑。现在云上的TSE已经支持了Apollo的托管,一键部署~ 还不心动么?这篇文章,我来介绍一下如何使用Java Spring Framework接入Apollo
请在Apollo配置中心做如下配置:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-mockserver</artifactId>
<version>1.8.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
app.id=100001
apollo.meta=http://172.17.16.14:8080
apollo.cluster=default
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces = name.yaml
# namespace application will always be loaded by default
export ENV=dev
export APOLLO_ACCESSKEY_SECRET=**************ac407c7
// Java Config
@Configuration
@EnableApolloConfig
public class ApolloConfig {
@Value("${app.key01:unknown}")
String hello01;
@Value("${app.key02:unknown}")
String hello02;
@Value("${app.key03:unknown}")
String hello03;
@Value("${app.key04:unknown}")
String hello04;
@PostConstruct // after the values are initialized, print their values
void print() {
System.out.println(this.getClass().getName() + " - " + hello01);
System.out.println(this.getClass().getName() + " - " + hello02);
System.out.println(this.getClass().getName() + " - " + hello03);
System.out.println(this.getClass().getName() + " - " + hello04);
}
}
@Component
@RefreshScope
public class ValuesDemoBean {
@Value("${app.key01:unknown}")
String hello01;
@Value("${app.key02:unknown}")
String hello02;
@Value("${app.key03:unknown}")
String hello03;
@Value("${app.key04:unknown}")
String hello04;
@PostConstruct // after the values are initialized, print their values
void print() {
System.out.println(this.getClass().getName() + " - " + hello01);
System.out.println(this.getClass().getName() + " - " + hello02);
System.out.println(this.getClass().getName() + " - " + hello03);
System.out.println(this.getClass().getName() + " - " + hello04);
}
}
@Component
@RefreshScope
@ConfigurationProperties(prefix = "app") // map object to keys with prefix
public class ObjectDemoBean {
private String key01;
private String key02;
private String key03;
private String key04;
public void setKey01(String key01) {
this.key01 = key01;
}
public void setKey02(String key02) {
this.key02 = key02;
}
public void setKey03(String key03) {
this.key03 = key03;
}
public void setKey04(String key04) {
this.key04 = key04;
}
@PostConstruct // after the values are initialized, print their values
void print() {
System.out.println(this.getClass().getName() + " - " + key01);
System.out.println(this.getClass().getName() + " - " + key02);
System.out.println(this.getClass().getName() + " - " + key03);
System.out.println(this.getClass().getName() + " - " + key04);
}
}
所有的键值都拿到了~ Voila!
配置服务需要允许一个服务同时从多个AppID(配置源)获取配置信息, 比如通用信息. DNS 服务器地址, 数据库连接地址. 在下面的案例中,我们演示如何从多个AppID获取配置信息。
私有的Namespace只能对当前的AppID可见,而公有的Namespace可以被关联到多个AppID下。所以生命周期是不同的。
请注意
@Component
@RefreshScope
@ConfigurationProperties(prefix = "global.url")
public class GlobalConfigDemoBean {
private String mysql;
private String dns;
public void setMysql(String mysql) {
this.mysql = mysql;
}
public void setDns(String dns) {
this.dns = dns;
}
@PostConstruct // after the values are initialized, print their values
void print() {
System.out.println(this.getClass().getName() + " - " + mysql);
System.out.println(this.getClass().getName() + " - " + dns);
}
}
就出来了!Fantastic!
基于@Value注入的消息会被自动更新,比如下面这个代码
@Configuration
@EnableApolloConfig
public class HelloConfig {
@Value("${app.key01:unknown}")
String hello01;
@Value("${app.key02:unknown}")
String hello02;
@PostConstruct // after the values are initialized, print their values
void print() {
System.out.println(this.getClass().getName() + " - " + hello01);
System.out.println(this.getClass().getName() + " - " + hello02);
}
}
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
@Component
@RefreshScope
@ConfigurationProperties(prefix = "global.url")
@Configuration
public class ApolloConfigRefreshBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Autowired
RefreshScope refreshScope;
// all related namespaces
@ApolloConfigChangeListener({ "name.yaml", "application", "TEST1.global-demo" })
private void someChangeHandler(ConfigChangeEvent changeEvent) {
System.out.println("Apollo Auto-refresh Started");
for (String changedKey : changeEvent.changedKeys()) {
ConfigChange configChange = changeEvent.getChange(changedKey);
String oldValue = configChange.getOldValue();
String newValue = configChange.getNewValue();
System.out.printf("[changedKey:%s,oldValue=%s, newValue:%s]", changedKey, oldValue, newValue);
}
refreshProperties(changeEvent);
System.out.println("Apollo Auto-refresh done");
}
public void refreshProperties(ConfigChangeEvent changeEvent) {
//all refreshScoped and annotated with @ConfigurationProperties
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
refreshScope.refreshAll();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
键值也自动刷新了 - Ja, voll!
app:
key01: hello01
key02: hello02
下面的配置会加载所有在app.id 100001的namespace application下的键值。
app.id=100001
apollo.meta=http://[apollo-meta-server]:8080
apollo.cluster=default
apollo.bootstrap.enabled=true
如果你想加载更多的namespace,比如yaml等,需要写如下的配置 apollo.bootstrap.namespaces = name.yaml,TEST1.global-demo
app.id=100001
apollo.meta=http://[apollo-meta-server]:8080
apollo.cluster=default
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces = name.yaml,TEST1.global-demo
# 这里关联namespace格式是[original-app.id].[namespace]
使用这个文档 来构建Mock Unit Test
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。