1. 概述

Spring Cloud Config 是 Spring Cloud 全家桶的核心组件之一。它通过集中式服务管理应用配置数据,实现配置与微服务部署的解耦。Spring Cloud Config 不仅内置属性仓库,还支持 Git、Consul、Eureka 等开源项目集成。

本文将深入探讨在 Spring Cloud Config 中覆盖远程属性值的多种方案,分析 Spring 2.4 版本引入的限制,以及 3.0 版本带来的变化。所有示例基于 Spring Boot 3.2.2。

2. 创建 Spring Config Server

2.1. 创建配置文件

application.properties 中定义的配置会共享给所有客户端应用。我们也可以为特定应用或 Profile 定义专属配置。

src/main/resources/config 目录下创建 baeldung.properties 文件(假设客户端应用名为 baeldung)。

2.2. 添加属性

baeldung.properties 中添加以下属性(后续将在客户端应用中使用):

hello=Hello Jane Doe!
welcome=Welcome Jane Doe!

src/main/resources/config/application.properties 中添加共享属性:

shared-property=This property is shared accross all client applications

2.3. Spring Boot Config Server 应用

创建配置服务端应用,需添加 spring-cloud-config-server 依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

主类添加 @EnableConfigServer 注解:

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServer.class, args);
    }
}

application.properties 中配置端口和配置存储路径:

server.port=8081
spring.cloud.config.server.native.searchLocations=classpath:/config

启动服务端(激活 native profile 使用文件系统作为配置仓库):

mvn spring-boot:run -Dspring-boot.run.profiles=native

验证共享属性是否可访问:

$ curl localhost:8081/unknownclient/default
{
  "name": "unknownclient",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": null,
  "state": null,
  "propertySources": [
    {
      "name": "classpath:/config/application.properties",
      "source": {
        "shared-property": "This property is shared accross all client applications"
      }
    }
  ]
}

验证应用专属属性:

$ curl localhost:8081/baeldung/default
{
  "name": "baeldung",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": null,
  "state": null,
  "propertySources": [
    {
      "name": "classpath:/config/baeldung.properties",
      "source": {
        "hello": "Hello Jane Doe!",
        "welcome": "Welcome Jane Doe!"
      }
    },
    {
      "name": "classpath:/config/application.properties",
      "source": {
        "shared-property": "This property is shared accross all client applications"
      }
    }
  ]
}

⚠️ 未禁用 spring.cloud.config.server.accept-empty(默认 true),即使应用不存在(如 unknownclient),也会返回共享属性。

3. 客户端应用

3.1. 项目设置与依赖

添加 spring-cloud-starter-configspring-boot-starter-web 依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

3.2. 创建客户端应用

创建客户端主类:

@SpringBootApplication
public class Client {
    public static void main(String[] args) {
        SpringApplication.run(Client.class, args);
    }
}

3.3. 获取配置

application.properties 中配置 Config Server 地址和应用名:

spring.cloud.config.name=baeldung
spring.config.import=optional:configserver:http://localhost:8081

3.4. 添加简单控制器

创建控制器展示配置属性:

@RestController
public class HelloController {

    @Value("${hello}")
    private String hello;

    @Value("${welcome}")
    private String welcome;

    @Value("${shared-property}")
    private String shared;

    @GetMapping("hello")
    public String hello() {
        return this.hello;
    }

    @GetMapping("welcome")
    public String welcome() {
        return this.welcome;
    }

    @GetMapping("shared")
    public String shared() {
        return this.shared;
    }
}

验证配置加载:

$ curl http://localhost:8080/hello
Hello Jane Doe!
$ curl http://localhost:8080/welcome
Welcome Jane Doe!
$ curl http://localhost:8080/shared
This property is shared accross all client applications

4. 在服务端覆盖属性

通过修改服务端配置可覆盖特定应用的属性。在服务端的 application.properties 中添加:

spring.cloud.config.server.overrides.hello=Hello Jane Doe – application.properties!

验证覆盖效果:

$ curl http://localhost:8080/hello
Hello Jane Doe - application.properties!

✅ 也可在共享配置文件 config/application.properties 中定义覆盖属性,优先级高于服务端主配置文件。

5. 在客户端覆盖属性

Spring Boot 2.4+ 后,无法直接通过客户端的 application.properties 覆盖远程属性。

5.1. 使用 Spring Profiles

本地 Profile 配置的属性优先级高于服务端应用配置。创建 application-development.properties

hello=Hello local property!

激活 development profile 启动客户端:

mvn spring-boot:run -Drun.profiles=development

验证覆盖:

$ curl http://localhost:8080/hello
Hello local property!

5.2. 使用占位符

通过占位符实现默认值覆盖。修改服务端 config/baeldung.properties

hello=${app.hello:Hello Jane Doe!}

在客户端 application.properties 中添加:

app.hello=Hello, overriden local property!

验证效果:

$ curl http://localhost:8080/hello
Hello, overriden local property!

⚠️ 若同时在 Profile 配置中定义 hello,Profile 配置优先级更高。

6. 传统配置方式

6.1. 加载外部配置

Spring Boot 2.4 前通过 bootstrap 机制管理外部配置。添加依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

创建 bootstrap.properties

spring.cloud.config.name=baeldung
spring.cloud.config.uri=http://localhost:8081

application.properties 中启用传统模式:

spring.config.use-legacy-processing=true

6.2. 启用覆盖能力

在服务端 baeldung.properties 中添加:

spring.cloud.config.overrideNone=true

✅ 此配置使外部属性不再优先于应用 JAR 内部定义的属性。

6.3. 覆盖服务端属性

在客户端 application.properties 中覆盖属性:

hello=localproperty

验证覆盖:

$ curl http://localhost:8080/hello
localproperty

6.4. 传统配置的废弃

Spring Boot 3.0+ 已移除传统配置支持,建议使用前述现代方案。

7. 总结

本文探讨了在 Spring Cloud Config 中覆盖远程属性值的多种方式:

  • 服务端覆盖:通过 spring.cloud.config.server.overrides 全局覆盖
  • 客户端覆盖
    • 使用 Spring Profiles(优先级最高)
    • 使用占位符提供默认值
  • ⚠️ 传统配置:仅适用于 Spring Boot 2.4-,3.0+ 已废弃

完整代码示例请参考 GitHub 仓库


原始标题:Overriding the Values of Remote Properties in Spring Cloud Config | Baeldung