spring 配置动态刷新 包括(apollp 和nacos)

Apollo

分布式 apollo 简介

Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。

本文主要介绍如何使用 apollo 与 springboot 实现动态刷新配置,如果之前不了解 apollo 可以查看如下文档

https://github.com/ctripcorp/apollo

学习了解一下 apollo,再来查看本文

apollo 与 spring 实现动态刷新配置本文主要演示 2 种刷新,一种基于普通字段刷新、一种基于 bean 上使用了 @ConfigurationProperties 刷新

1、普通字段刷新(@Value)

== 不需要额外配置,直接就可以动态刷新 ==

a、pom.xml 配置

        <dependency>
            <groupId>com.ctrip.framework.apollo</groupId>
            <artifactId>apollo-client</artifactId>
            <version>1.6.0</version>
        </dependency>


b、客户端配置 AppId,Apollo Meta Server

此配置有多种方法,本示例直接在 application.yml 配置,配置内容如下

app:
  id: ${
   
   spring.application.name}
apollo:
  meta: http://192.168.88.128:8080,http://192.168.88.129:8080
  bootstrap:
    enabled: true
    eagerLoad:
      enabled: true


c、项目中启动类上加上 @EnableApolloConfig 注解,形如下

@SpringBootApplication
@EnableApolloConfig(value = {
   
   "application","user.properties","product.properties","order.properties"})
public class ApolloApplication {
   
   

    public static void main(String[] args) {
   
   

        SpringApplication.run(ApolloApplication.class, args);
    }

}


@EnableApolloConfig 不一定要加在启动类上,加在被 spring 管理的类上即可

d、在需刷新的字段上配置 @Value 注解,形如

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

通过以上三步就可以实现普通字段的动态刷新

2、bean 使用 @ConfigurationProperties 动态刷新

bean 使用 @ConfigurationProperties 注解目前还不支持自动刷新,得编写一定的代码实现刷新。目前官方提供 2 种刷新方案

  • 基于 RefreshScope 实现刷新
  • 基于 EnvironmentChangeEvent 实现刷新
  • 本文再提供一种,当 bean 上如果使用了 @ConditionalOnProperty 如何实现刷新

a、基于 RefreshScope 实现刷新

1、pom.xml 要额外引入

    <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-context</artifactId>
            <version>2.0.3.RELEASE</version>
        </dependency>



2、bean 上使用 @RefreshScope 注解

@Component
@ConfigurationProperties(prefix = "product")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@RefreshScope
public class Product {
   
   

    private Long id;

    private String productName;

    private BigDecimal price;

}


3、利用 RefreshScope 搭配 @ApolloConfigChangeListener 监听实现 bean 的动态刷新,其代码实现如下

 @ApolloConfigChangeListener(value="product.properties")
    private void refresh(ConfigChangeEvent changeEvent){
   
   

        refreshScope.refresh("product");

        PrintChangeKeyUtils.printChange(changeEvent);
    }


@ApolloConfigChangeListener 注解

参数​​ ​​作用​​ ​​类型​​ ​​默认值​​ ​​示例​​
value / configNames 指定要监听的 Apollo 命名空间(namespace)列表 String[] 空数组(监听 application) @ApolloConfigChangeListener({“app1”, “app2”})
interestedKeyPrefixes 仅监听以指定前缀开头的配置项变更(过滤无关配置) String[] 空数组(监听所有) @ApolloConfigChangeListener(interestedKeyPrefixes = “spring.redis”)
interestedKeys 明确指定要监听的配置项 Key(完全匹配) String[] 空数组(监听所有) @ApolloConfigChangeListener(interestedKeys = {“timeout”, “max.retries”})
ignoreNamespaceNotFound 是否忽略未找到命名空间的错误(避免启动失败) boolean false(严格模式) @ApolloConfigChangeListener(value = “optional-ns”, ignoreNamespaceNotFound = true)

b、基于 EnvironmentChangeEvent 实现刷新

利用 spring 的事件驱动配合 @ApolloConfigChangeListener 监听实现 bean 的动态刷新,其代码如下

@Component
@Slf4j
public class UserPropertiesRefresh implements ApplicationContextAware {
   
   

    private ApplicationContext applicationContext;



    @ApolloConfigChangeListener(value="user.properties",interestedKeyPrefixes = {
   
   "user."})
    private void refresh(ConfigChangeEvent changeEvent){
   
   
        applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));

        PrintChangeKeyUtils.printChange(changeEvent);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
   
   
        this.applicationContext = applicationContext;
    }




}



c、当 bean 上有 @ConditionalOnProperty 如何实现刷新

当 bean 上有 @ConditionalOnProperty 注解时,上述的两种方案可以说失效了,因为 @ConditionalOnProperty 是一个条件注解,当不满足条件注解时,bean 是没法注册到 spring 容器中的。如果我们要实现此种情况的下的动态刷新,我们就得自己手动注册或者销毁 bean 了。其实现流程如下

1、当满足条件注解时,则手动创建 bean,然后配合 @ApolloConfigChangeListener 监听该 bean 的属性变化。当该 bean 属性有变化时,手动把属性注入 bean。同时刷新依赖该 bean 的其他 bean

2、当不满足条件注解时,则手动从 spring 容器中移除 bean,同时刷新依赖该 bean 的其他 bean

其刷新核心代码如下

public class OrderPropertiesRefresh implements ApplicationContextAware {
   
   

    private ApplicationContext applicationContext;

    @ApolloConfig(value = "order.properties")
    private Config config;


    @ApolloConfigChangeListener
Spring Boot 3 中动态刷新Nacos 获取的 MySQL 配置,可按以下方式操作: ### 引入依赖 要确保项目的 `pom.xml` 中包含必要的依赖,特别是 Nacos 配置 Spring Cloud 配置刷新相关的依赖。示例如下: ```xml <dependencies> <!-- Nacos 配置依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>合适的版本号</version> </dependency> <!-- Spring Cloud 配置刷新依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-config</artifactId> </dependency> </dependencies> ``` ### 配置 Nacos 在 `bootstrap.yml` 或 `application.yml` 中配置 Nacos 的连接信息,示例如下: ```yaml spring: cloud: nacos: config: server-addr: 127.0.0.1:8848 # Nacos 服务器地址 namespace: your-namespace # 命名空间 group: your-group # 配置分组 file-extension: yml # 配置文件扩展名 extension-configs[0]: data-id: datasource.yml # 配置的 Data ID refresh: true # 开启动态刷新 ``` ### 配置 MySQL 数据源 在 Nacos 控制台创建名为 `datasource.yml` 的配置文件,内容如下: ```yaml spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/your_database username: your_username password: your_password ``` ### 启用动态刷新 在需要动态刷新配置的类上添加 `@RefreshScope` 注解。例如,创建一个配置类: ```java import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.stereotype.Component; @Component @RefreshScope @ConfigurationProperties(prefix = "spring.datasource") public class DataSourceConfig { private String url; private String username; private String password; private String driverClassName; // Getters and Setters public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } } ``` ### 验证动态刷新 当在 Nacos 控制台修改 `datasource.yml` 中的 MySQL 配置后,Spring Boot 应用会自动检测到配置变更并刷新数据源配置,无需重启应用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值