分布式配置中心 Apollo 实战 - Spring Boot 整合 Apollo 分布式配置中心
|字数总计:1.7k|阅读时长:9分钟|阅读量:|
Spring Boot 整合 Apollo 分布式配置中心
核心依赖
1 2 3 4 5 6
| <dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</artifactId> <version>1.9.2</version> </dependency>
|
创建工程
创建 Spring Boot
项目 xuejian-apollo
,引入 apollo
客户端及 web
依赖,完整 pom.xml
文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>io.github.llnancy</groupId> <artifactId>xuejian-parent</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion>
<artifactId>xuejian-apollo</artifactId>
<properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${springboot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<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.9.2</version> </dependency> </dependencies> </project>
|
基本配置
在 Spring Boot
项目的配置文件 application.yml
中添加以下配置项:
1 2 3 4 5 6 7 8 9
| apollo: bootstrap: enabled: true namespaces: application.yml eagerLoad: enabled: true
app: id: xuejian-apollo
|
注意还需要在 VM Options
中配置环境 env
和 Meta Server
的地址(apollo.meta
):
1
| -Denv=DEV -Dapollo.meta=http://localhost:8080
|
添加配置
todo
读取配置
可使用 @ApolloConfig
、@ApolloJsonValue
、@Value
、@ConfigurationProperties
及 @ApolloConfigChangeListener
等注解读取配置。
使用 @ApolloConfig 注解
使用 @ApolloConfig
注解自动注入对应 namespace
的 Config
对象,代码示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package io.github.llnancy.xuejian.apollo.web.controller;
import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.spring.annotation.ApolloConfig; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
@RestController public class ApolloConfigController {
@ApolloConfig(value = "application.yml") private Config config;
@GetMapping("/config") public String getConfig(String key) { return config.getProperty(key, null); } }
|
注入了 application.yml
这个 namespace
对应的 Config
对象,从而可以读取 key-value
类型的字符串配置项。
使用 @ApolloJsonValue 注解
使用 @ApolloJsonValue
注解把配置的 json
字符串自动注入为 Java Bean
对象,代码示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package io.github.llnancy.xuejian.apollo.web.controller;
import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.spring.annotation.ApolloConfig; import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue; import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController public class ApolloConfigController {
@ApolloJsonValue("${xuejian.apollo.jsonstr:[]}") private List<JsonBean> jsonBeanList;
@Data public static class JsonBean { private String name; private Integer age; }
@GetMapping("/json-value") public List<JsonBean> getJsonValue() { return jsonBeanList; } }
|
注意:yml
格式下配置 json
字符串时需要用单引号 ''
将整个 json
串括起来进行转义。
使用 @Value 注解
使用 @Value
注释实际上是通过 Spring
的 Placeholder
占位符的形式来注入配置项,其格式支持 SpEL
表达式,例如 ${key:defaultValue}
,冒号左边的 key
是配置项,冒号右边的 defaultValue
是默认值(可不提供)。代码示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| package io.github.llnancy.xuejian.apollo.web.controller;
import com.ctrip.framework.apollo.Config; import com.ctrip.framework.apollo.spring.annotation.ApolloConfig; import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController @Slf4j public class ApolloConfigController {
@Value("${xuejian.apollo.name:defaultVal}") private String key; @Value("#{'${xuejian.apollo.jsonstr:[]}'.split(',')}") private List<String> jsonList;
@GetMapping("/placeholder") public void getConfigByPlaceholder() { log.info("key={}, jsonList={}", key, jsonList); } }
|
配合 @ConfigurationProperties 注解使用
首先定义一个 config
配置类代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package io.github.llnancy.xuejian.apollo.config;
import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration;
import java.util.List;
@ConfigurationProperties(prefix = "xuejian.apollo") @Configuration @Getter @Setter public class XueJianApolloConfig {
private String name; private List<String> jsonstr; }
|
然后就可以通过注入的方式进行使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| package io.github.llnancy.xuejian.apollo.web.controller;
import config.io.github.llnancy.xuejian.apollo.XueJianApolloConfig; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController @Slf4j public class ApolloConfigController {
@Autowired private XueJianApolloConfig xueJianApolloConfig;
@GetMapping("/configurationProperties") public void getXueJianApolloConfig() { String name = xueJianApolloConfig.getName(); List<String> jsonstr = xueJianApolloConfig.getJsonstr(); log.info("name={}, jsonstr={}", name, jsonstr); } }
|
使用 @ApolloConfigChangeListener 注解
使用 @ApolloConfigChangeListener
注解可自动注册 ConfigChangeListener
监听器监听配置项变更事件,示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package io.github.llnancy.xuejian.apollo.config;
import com.ctrip.framework.apollo.model.ConfigChange; 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.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Configuration;
import javax.annotation.Nonnull; import java.util.Set;
@Configuration @Slf4j public class ApolloRefresherConfig implements ApplicationContextAware {
private ApplicationContext applicationContext;
@ApolloConfigChangeListener(value = {"application", "application.yml"}) private void refreshConfig(ConfigChangeEvent configChangeEvent) { log.info("listened config change event, the namespace is {}", configChangeEvent.getNamespace()); Set<String> changedKeys = configChangeEvent.changedKeys(); for (String changedKey : changedKeys) { ConfigChange change = configChangeEvent.getChange(changedKey); log.info("Found change - key: {}, oldValue: {}, newValue: {}, changeType: {}", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType()); } this.applicationContext.publishEvent(new EnvironmentChangeEvent(changedKeys)); }
@Override public void setApplicationContext(@Nonnull ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
|
对于使用 @ConfigurationProperties
注解注入的属性,需要发布 org.springframework.cloud.context.environment.EnvironmentChangeEvent
事件触发属性值的更新。所以需要在 pom.xml
中添加 spring-cloud-context
依赖:
1 2 3 4 5 6
| <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-context</artifactId> <version>3.1.1</version> </dependency>
|