SpringBoot 配置热加载

SpringCloudKubernetes

Posted by Claire on September 15, 2023

springboot的配置通常是在以下文件中进行配置,在打包时就涵盖,或者在发布时指定外部配置文件:

  • application.properties
  • application.yaml
  • application-{env}.properties
  • application-{env}.yaml

通常一旦程序发布就不能修改配置,那有什么办法能够修改这上下文里的参数呢? 以下方法涉及:

  • SpringBoot SpringCloud
  • 动态代理
  • 类加载
  • ContextRefresher.refresh()上下文刷新

以下测试版本说明:

  • springcloud: 4.0.4
  • springboot: 3.1.0

1、从actuator端点刷新应用属性

主要用 SpringCloud 的上下文参数刷新的功能,接口 /actuator/refresh 的端点,实现应用属性的实时刷新。

1.1 @ConfigurationProperties + /actuator/refresh

1.引入springboot框架 2.引入 springcloud 依赖,springboot-actuator 依赖,开启 refresh 端口

application.yaml:

server:
  port: 8080
spring:
  application:
    name: springboot-config-refresh
management:
  endpoints:
    web:
      exposure:
        include: refresh
demo:
  message: files

pom.xml:

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter</artifactId>
            <version>${spring-cloud.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>

3.书写配置类 MyConfig ,结合 @ConfigurationProperties 这个注解是扫描生效的重点

MyConfig.class

@Data
@Configuration
@ConfigurationProperties(prefix = "demo")
public class MyConfig {

    private String message ="default message";

}

4.书写值查询的接口进行验证

@RestController
@RequestMapping
public class ValueController {
    @Autowired
    private MyConfig myConfig;

    @GetMapping
    public String value(){
     return myConfig.getMessage();
    }
}

5.请求API

请求API获取初始配置

curl --location --request GET '127.0.0.1:8080/'

files
  • war包部署或本地测试,可以修改class下配置文件application.yaml
  • jar包部署,需要启动时指定外部的文件,--spring.config.location=/Users/chenzy/application.yaml,此时修改外部文件保存即可
server:
  port: 8080
spring:
  application:
    name: springboot-config-refresh
management:
  endpoints:
    web:
      exposure:
        include: refresh
  endpoint:
    refresh:
      enabled: true
demo:
  message: newfiles

请求 /actuator/refresh 触发旧bean的销毁,并返回修改项

curl --location --request POST '127.0.0.1:8080/actuator/refresh' \
--header 'Content-Type: application/json'

[
    "demo.message"
]

请求API获取新配置

curl --location --request GET '127.0.0.1:8080/'

newfiles

配置被刷新,符合预期

1.2 @Value + @RefreshScope + /actuator/refresh

以下演示 @Value 在指定的配置类中,而非 Controller 中直接引入 1.2步骤同(1.1 @ConfigurationProperties + /actuator/refresh)

3.书写 MyValue ,使用 @Value 的注解获取配置文件参数值

@Data
@Configuration
@RefreshScope
public class MyValue {
    @Value("${demo.value}")
    private String demoValue;
}

application.yaml

server:
  port: 8080
spring:
  application:
    name: springboot-config-refresh
management:
  endpoints:
    web:
      exposure:
        include: refresh
  endpoint:
    refresh:
      enabled: true
demo:
  message: files
  value: files

4.书写值查询的接口进行验证

@RestController
@RequestMapping
public class ValueController {
    @Autowired
    private MyConfig myConfig;
    @Autowired
    private MyValue myValue;

    @GetMapping
    public String value(){
     return myConfig.getMessage();
    }

    @GetMapping("demo")
    private String demoValue(){
        return myValue.getDemoValue();
    }
}

5.请求API

请求API获取初始配置

curl --location --request GET '127.0.0.1:8080/demo'

files

参照 上一个方法去修改对应配置的值 调用 /actuator/refresh 方法后,能够获取到最新值

curl --location --request POST '127.0.0.1:8080/actuator/refresh' \
--header 'Content-Type: application/json'

[
    "demo.value"
]
curl --location --request GET '127.0.0.1:8080/demo'

newfiles

2、从外部文件加载和更新应用属性

这种方法目前用处不多,可以自行参考demo