SpringBoot/SpringCloud: 应用配置项热加载与动态刷新

  • 1、从actuator端点刷新应用属性
    • 1.1 @ConfigurationProperties + /actuator/refresh
    • 1.2 @Value + @RefreshScope + /actuator/refresh
  • 2、从外部文件加载和更新应用属性

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.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
            <version>${spring-cloud.version}version>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-actuatorartifactId>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.22version>
        dependency>
    dependencies>
  1. 书写配置类 MyConfig ,结合 @ConfigurationProperties 这个注解是扫描生效的重点

MyConfig.class

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

    private String message ="default message";

}
  1. 书写值查询的接口进行验证
@RestController
@RequestMapping
public class ValueController {
    @Autowired
    private MyConfig myConfig;

    @GetMapping
    public String value(){
     return myConfig.getMessage();
    }
}
  1. 请求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)

  1. 书写 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
  1. 书写值查询的接口进行验证
@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();
    }
}
  1. 请求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

你可能感兴趣的:(SpringCloud,javaweb,spring,boot,spring,cloud,java)