SpringBoot整合Nacos自动刷新配置

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,182元/月
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: Nacos作为SpringBoot服务的注册中心和配置中心。在NacosServer中修改配置文件,在SpringBoot不重启的情况下,获取到修改的内容。本例将在配置文件中配置一个 cml.age=100 的配置项,程序中编写一个方法读取配置文件,并通过 Get--->/test/age 接口提供给浏览器访问。若配置文件中的 age 修改为 200 ,不用重新启动程序,直接访问 /test/age 接口,将获取到最新的值 200若配置文件中没有age 的配置项,或干脆没有 cml 的配置项,访问 /test/age 接口将返回默认的值 18

目的

Nacos作为SpringBoot服务的注册中心和配置中心。

在NacosServer中修改配置文件,在SpringBoot不重启的情况下,获取到修改的内容。

本例将在配置文件中配置一个 cml.age=100 的配置项,程序中编写一个方法读取配置文件,并通过 Get--->/test/age 接口提供给浏览器访问。

  • 若配置文件中的 age 修改为 200 ,不用重新启动程序,直接访问 /test/age 接口,将获取到最新的值 200
  • 若配置文件中没有age 的配置项,或干脆没有 cml 的配置项,访问 /test/age 接口将返回默认的值 18

环境

  • SpringCloud:2020.0.3
  • SpringCloudAlibaba:2021.1
  • SpringBoot:2.5.2

pom

pom中引入 nacos 相关配置:discovery,config,bootstrap

网上有人说,需要引入 actuator ,其实不用。也没有 SpringSecurity 拦截的问题,NacosClient 端定时从 NacosServer 端拉取最新配置,以http方式请求。


  <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring.cloud.dependencies}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring.cloud.alibaba.dependencies}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!-- nacos-discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
           <!--nacos config -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
         <!--bootstrap-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
    </dependencies>

配置文件

bootstrap.yml


server:
  port: 9556
spring:
  application:
    name: app
  profiles:
    active: test
    nacos:
      discovery:
        username: nacos
        password: nacos
        server-addr: 192.168.1.61:8848
      config:
        server-addr: 192.168.1.61:8848
        file-extension: yaml

app-dev.yaml

此配置指 NacosServer 中的配置文件 app-dev.yaml ,仅截取 cml.age 部分

cml:
   age: 100

代码

  • RefreshScope注解:必须加在 controller 上面,加在主启动内上面不好使。哪些资源需要自动刷新配置就在该controller上面添加此注解,可封装一个 BaseController 。
  • @Value("${cml.age:18}"):读取配置文件中的 cml.age 配置项值,赋给变量 age ,默认值为 18
  • getAge:获取年龄接口
  • /test/age接口需要添加到 Security.permitAll

问题:RefreshScope注解为什么一定要添加在 controller 上面?为什么在主启动类上面添加不生效


     @RefreshScope
     @Api(tags = "测试 - api")
     @Slf4j
     @RestController
     @RequestMapping("/test")
     public class TestController {

         /**
          * 获取配置文件中的 cml.age 内容,若未获取到,默认值为18
          */
         @Value("${cml.age:18}")
         private String age;

         @ApiOperation(value = "获取年龄 - 测试配置自动刷新", notes = "获取年龄 - 测试配置自动刷新")
         @GetMapping("/age")
         public String getAge() {
             return age;
         }
     }

日志

开启 nacos-refresh 日志,打印配置内容更新情况

logging:
  level:
     com.alibaba.cloud.nacos.refresh: debug

打印的日志:

2022-01-28 13:43:30.574 [com.alibaba.nacos.client.Worker.longPolling.fixed-192.168.1.61_8848-zjrkm-admin] DEBUG com.alibaba.cloud.nacos.refresh.NacosContextRefresher.innerReceive:136 - Refresh Nacos config group=DEFAULT_GROUP,dataId=identityQrCodeAdmin-service-cml-test.yaml,configInfo=spring:
  application:
    name: 
    .
    .
    .
    .
    .

测试

在不重启SpringBoot服务的情况,多次在 NacosServer 中修改 cml.age 配置项的值,然后通过浏览器访问 /test/age 接口,发现每次都可以获取到最新的 age 值。

特殊的情况

当项目集成了 SpringSecurity 的时候,如果在 UserDetailsService 实现类上添加 RefreshScope 注解,并在类中直接使用 @Value 获取配置文件的内容,会导致用户在登录的时候找不到该类,从而无法调用loadUserByUsername 方法做用户名密码校验,进而登录功能无法使用。

解决方案是:

  • 新建一个配置类(假设类名为 Account ),使用 ConfigurationProperties 将需要的配置注入到类属性;并在类上添加 RefreshScope 注解
  • 将 Account 类注入容器,UserDetailsService 实现类中将 Account 类 Autowired 进来再使用

核心代码:
Account 类:


import lombok.Data;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import java.io.Serializable;
@RefreshScope
@Component
@ConfigurationProperties(prefix = "cml.admin")
@Data
@ToString
public class Account  implements Serializable {
    private  String defaultUserName;
    private  String defaultPassword;
    private  String defaultUserName1;
    private  String defaultPassword1;
}

UserDetailsService 实现类:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private Account account;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (account.getDefaultUserName().equals(username)) {
            String password = passwordEncoder.encode(account.getDefaultPassword());
            return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }
        if (account.getDefaultUserName1().equals(username)) {
            String password = passwordEncoder.encode(account.getDefaultPassword1());
            return new User(username, password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin1"));
        }
        return null;
    }
}
目录
相关文章
|
1月前
|
人工智能 Java Nacos
基于 Spring AI Alibaba + Nacos 的分布式 Multi-Agent 构建指南
本文将针对 Spring AI Alibaba + Nacos 的分布式多智能体构建方案展开介绍,同时结合 Demo 说明快速开发方法与实际效果。
1562 54
|
2月前
|
XML Java Nacos
Spring Boot 整合Nacos 版本兼容适配 史上最详细文档
本文介绍SpringBoot整合Nacos的完整流程,涵盖Nacos下载安装、配置中心与服务发现集成、版本兼容性问题及实战配置。重点解决SpringBoot 3.3.0与Nacos版本适配难题,推荐使用Spring Cloud Alibaba方案,并提供项目开源地址供参考学习。
|
4月前
|
Java Spring
Spring Boot配置的优先级?
在Spring Boot项目中,配置可通过配置文件和外部配置实现。支持的配置文件包括application.properties、application.yml和application.yaml,优先级依次降低。外部配置常用方式有Java系统属性(如-Dserver.port=9001)和命令行参数(如--server.port=10010),其中命令行参数优先级高于系统属性。整体优先级顺序为:命令行参数 &gt; Java系统属性 &gt; application.properties &gt; application.yml &gt; application.yaml。
952 0
|
4月前
|
Dubbo 数据可视化 Java
整合SpringBoot、Dubbo与Nacos:一个快速入门教程
经过上述步骤,消费者模块成功引用了生产者提供的服务,并通过Spring Web将服务映射到了特定的URL路径上。消费者模块成功地调用并展示了生产者提供的数据,并在不移除特定依赖项的情况下确保了系统的正常运行。
|
1月前
|
JavaScript Java Maven
【SpringBoot(二)】带你认识Yaml配置文件类型、SpringMVC的资源访问路径 和 静态资源配置的原理!
SpringBoot专栏第二章,从本章开始正式进入SpringBoot的WEB阶段开发,本章先带你认识yaml配置文件和资源的路径配置原理,以方便在后面的文章中打下基础
271 3
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
532 5
|
2月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
179 0
探索Spring Boot的@Conditional注解的上下文配置
|
3月前
|
安全 算法 Java
在Spring Boot中应用Jasypt以加密配置信息。
通过以上步骤,可以在Spring Boot应用中有效地利用Jasypt对配置信息进行加密,这样即使配置文件被泄露,其中的敏感信息也不会直接暴露给攻击者。这是一种在不牺牲操作复杂度的情况下提升应用安全性的简便方法。
979 10
|
8月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
1120 0
|
4月前
|
人工智能 安全 Java
Spring Boot yml 配置敏感信息加密
本文介绍了如何在 Spring Boot 项目中使用 Jasypt 实现配置文件加密,包含添加依赖、配置密钥、生成加密值、在配置中使用加密值及验证步骤,并提供了注意事项,确保敏感信息的安全管理。
1125 1

热门文章

最新文章

下一篇
oss云网关配置