SpringBoot集成Apollo
2026/1/15大约 5 分钟ApolloApolloSpringBoot分布式配置中心配置管理灰度发布动态配置
1. 创建应用
1.1 在 Apollo Portal 创建应用
- 登录 Apollo Portal(http://localhost:8070)
- 点击「创建应用」
- 填写应用信息:
- 应用ID:
demo-service(唯一标识,不可修改) - 应用名称:
演示服务 - 部门:选择所属部门
- 应用负责人:选择负责人
- 应用ID:
1.2 添加配置
在应用的 application 命名空间中添加配置:
# 数据库配置
spring.datasource.url = jdbc:mysql://localhost:3306/demo
spring.datasource.username = root
spring.datasource.password = 123456
# 自定义配置
app.name = Demo Application
app.timeout = 3000
app.feature.enabled = true点击「发布」按钮发布配置。
2. Spring Boot 项目集成
2.1 添加依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>2.1.0</version>
</dependency>如果使用 Spring Boot Starter:
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client-config-data</artifactId>
<version>2.1.0</version>
</dependency>2.2 配置 Apollo 连接信息
在 application.yml 中配置:
# Apollo 配置
app:
id: demo-service # 应用ID,需要与Portal中创建的一致
apollo:
meta: http://localhost:8080 # Config Service 地址
bootstrap:
enabled: true # 启用 Apollo 配置
namespaces: application # 加载的命名空间,多个用逗号分隔
eagerLoad:
enabled: true # 饥饿加载或者使用 application.properties:
app.id=demo-service
apollo.meta=http://localhost:8080
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application
apollo.bootstrap.eagerLoad.enabled=true2.3 指定环境
Apollo 环境可以通过以下方式指定(优先级从高到低):
方式一:JVM 参数
java -Denv=DEV -jar your-app.jar方式二:环境变量
export ENV=DEV
java -jar your-app.jar方式三:配置文件
在 classpath:/META-INF/app.properties 中配置:
env=DEV方式四:server.properties
在 /opt/settings/server.properties 中配置:
env=DEV2.4 启用 Apollo 配置
在启动类上添加 @EnableApolloConfig 注解:
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableApolloConfig // 启用 Apollo 配置
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}提示
如果使用了 apollo.bootstrap.enabled=true,则不需要添加 @EnableApolloConfig 注解。
3. 使用配置
3.1 使用 @Value 注解
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class AppConfig {
@Value("${app.name:默认名称}")
private String appName;
@Value("${app.timeout:5000}")
private int timeout;
@Value("${app.feature.enabled:false}")
private boolean featureEnabled;
// getter methods
public String getAppName() {
return appName;
}
public int getTimeout() {
return timeout;
}
public boolean isFeatureEnabled() {
return featureEnabled;
}
}3.2 使用 @ConfigurationProperties
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private String name;
private int timeout;
private Feature feature = new Feature();
// getter and setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public Feature getFeature() {
return feature;
}
public void setFeature(Feature feature) {
this.feature = feature;
}
public static class Feature {
private boolean enabled;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}3.3 使用 Apollo API 直接获取
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import org.springframework.stereotype.Service;
@Service
public class ConfigDemoService {
public String getConfig(String key) {
// 获取默认 namespace (application) 的配置
Config config = ConfigService.getAppConfig();
return config.getProperty(key, "默认值");
}
public String getConfigFromNamespace(String namespace, String key) {
// 获取指定 namespace 的配置
Config config = ConfigService.getConfig(namespace);
return config.getProperty(key, "默认值");
}
public int getIntConfig(String key) {
Config config = ConfigService.getAppConfig();
return config.getIntProperty(key, 0);
}
public boolean getBooleanConfig(String key) {
Config config = ConfigService.getAppConfig();
return config.getBooleanProperty(key, false);
}
}4. 配置热更新
4.1 @Value 自动刷新
默认情况下,使用 @Value 注入的配置会自动刷新。但需要注意:
- 配置变更后,Bean 中的字段值会自动更新
- 如果配置在 Bean 初始化时被使用(如构造函数),则不会自动更新
4.2 @ConfigurationProperties 自动刷新
@ConfigurationProperties 默认支持自动刷新,配置变更后会自动更新属性值。
4.3 监听配置变更
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class ConfigChangeHandler {
@PostConstruct
public void init() {
Config config = ConfigService.getAppConfig();
// 监听所有配置变更
config.addChangeListener(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
System.out.println("配置发生变更,namespace: " + changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.printf("配置变更 - key: %s, oldValue: %s, newValue: %s, changeType: %s%n",
change.getPropertyName(),
change.getOldValue(),
change.getNewValue(),
change.getChangeType());
}
}
});
// 监听指定 key 的变更
config.addChangeListener(changeEvent -> {
if (changeEvent.isChanged("app.timeout")) {
ConfigChange change = changeEvent.getChange("app.timeout");
System.out.println("timeout 配置变更: " + change.getNewValue());
// 执行相应的业务逻辑
}
});
}
}4.4 使用 @ApolloConfigChangeListener 注解
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import org.springframework.stereotype.Component;
@Component
public class ApolloConfigChangeListener {
/**
* 监听 application namespace 的配置变更
*/
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.printf("配置变更 - key: %s, oldValue: %s, newValue: %s%n",
key, change.getOldValue(), change.getNewValue());
}
}
/**
* 监听指定 namespace 的配置变更
*/
@ApolloConfigChangeListener(value = {"application", "datasource"})
public void onMultiNamespaceChange(ConfigChangeEvent changeEvent) {
System.out.println("Namespace: " + changeEvent.getNamespace());
}
/**
* 监听指定 key 的配置变更
*/
@ApolloConfigChangeListener(interestedKeys = {"app.timeout", "app.name"})
public void onSpecificKeyChange(ConfigChangeEvent changeEvent) {
// 只有 app.timeout 或 app.name 变更时才会触发
}
/**
* 监听指定前缀的配置变更
*/
@ApolloConfigChangeListener(interestedKeyPrefixes = {"spring.datasource"})
public void onDatasourceChange(ConfigChangeEvent changeEvent) {
// 只有 spring.datasource.* 变更时才会触发
System.out.println("数据源配置变更,需要刷新数据源连接池");
}
}5. 多 Namespace 配置
5.1 配置多个 Namespace
apollo:
bootstrap:
enabled: true
namespaces: application,datasource,redis # 多个 namespace 用逗号分隔5.2 指定 Namespace 获取配置
import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig;
@SpringBootApplication
@EnableApolloConfig(value = {"application", "datasource", "redis"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}5.3 Namespace 配置优先级
当多个 Namespace 中存在相同的 key 时,按照配置顺序,后面的会覆盖前面的。
# 假设 application 和 datasource 都有 db.url 配置
# datasource 在后面,所以 datasource 中的 db.url 会生效
apollo:
bootstrap:
namespaces: application,datasource6. 本地缓存
6.1 缓存机制
Apollo 客户端会将配置缓存到本地文件,即使 Config Service 不可用,也能从本地缓存读取配置。
默认缓存路径:
- Mac/Linux:
/opt/data/{appId}/config-cache - Windows:
C:\opt\data\{appId}\config-cache
6.2 自定义缓存路径
apollo:
cache-dir: /custom/path/apollo-cache或者通过 JVM 参数:
java -Dapollo.cache-dir=/custom/path/apollo-cache -jar your-app.jar7. 完整示例
7.1 项目结构
7.2 测试接口
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${app.name:unknown}")
private String appName;
@Value("${app.timeout:5000}")
private int timeout;
@Autowired
private AppConfig appConfig;
@GetMapping("/value")
public String getValueConfig() {
return String.format("appName: %s, timeout: %d", appName, timeout);
}
@GetMapping("/bean")
public String getBeanConfig() {
return String.format("appName: %s, timeout: %d, featureEnabled: %s",
appConfig.getAppName(),
appConfig.getTimeout(),
appConfig.isFeatureEnabled());
}
}7.3 测试配置热更新
- 启动应用
- 访问 http://localhost:8080/config/value 查看当前配置
- 在 Apollo Portal 修改配置并发布
- 再次访问接口,查看配置是否更新
8. 总结
本节我们学习了 Spring Boot 集成 Apollo 的完整流程:
- 添加依赖:引入 apollo-client 依赖
- 配置连接:配置 app.id 和 apollo.meta
- 使用配置:通过 @Value、@ConfigurationProperties 或 API 获取配置
- 配置热更新:监听配置变更,实现动态刷新
下一节我们将学习 Apollo 的高级特性,包括灰度发布、公共配置等。
