项目实践-SpringBoot实时获取Nacos配置文件内容(.yaml文件)

项目实践-SpringBoot实时获取Nacos配置文件内容(.yaml文件)

**书山有路勤为径,学海无涯苦作舟**
记录程序员生活点点滴滴,希望记录的内容能帮助到努力爬山的各位伙伴!

标签:Nacos/yaml文件

前言

  1. 业务场景:分布式业务系统中各组件属性在Nacos配置列表中config.yaml文件中进行灵活配置,系统通过接口从config.yaml文件中获取各组件属性再进行页面渲染。
  2. 功能要求:
  3. config.yaml中各组件属性可以灵活修改/增删,接口都可以获取最新的配置内容,并且不需要重启服务。
  4. 接口返回前端的内容不能改变config.yaml内容的数据格式(yaml文件格式)。

一、SpringBoot集成Nacos

1.引入Maven依赖

	<!--nacos依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>1.4.1</version>
    </dependency>

在实现方式中会涉及对yaml文件的处理,因此需要引入yaml相关jar包

	<dependency>
        <groupId>org.yaml</groupId>
        <artifactId>snakeyaml</artifactId>
        <version>1.23</version>
    </dependency>

2.Nacos基本配置

server:
  port: 18010
spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: project-proxy
  server:
    ip: 127.0.0.1
  cloud:
    nacos:
    	common-file: common-config.yaml
    	common-file-group: prod
      discovery:
        server-addr: ${spring.server.ip}:8848
        group: prod
      config:
        server-addr: ${spring.server.ip}:8848
        group: prod
        prefix: ${spring.application.name}
        file-extension: yaml

备注:
5. 在我的项目中Nacos的基本配置信息放在bootstrap.yml文件中
6. common-file: common-config.yaml是实时读取目标文件Data_id,在Nacos中提前已经配置完成
7. common-file-group: prod是目标文件的Group

二、实现Nacos中yaml文件读取

整体思路

  1. 利用配置文件的DATA_ID和GROUP,通过Nacos开放接口获取yaml文件内容
  2. 将获取的yaml文件内容写入到固定路径下的.yaml文件中去
  3. 读取yaml文件内容并处理封装提供给前端

1.具体实现类

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author Miracle
 * @title: WebConfigController
 * @projectName proxy
 * @description: 【config-api】
 * @date 2021/6/215:07
 */
@RestController
@RefreshScope
@RequestMapping("/config")
public class WebConfigController {

	/**
     * DATA_ID
     */
    @Value("${spring.cloud.nacos.common-file}")
    private String DataId ;

	/**
     * GROUP
     */
    @Value("${spring.cloud.nacos.common-file-group}")
    private String group ;

    /**
     * 存储配置信息文件路径
     */
    final String FilePath = WebConfigController.class.getClassLoader().getResource("webconfig.yml").getPath();

    /**
     * 默认nacos地址
     */
    @Value("${spring.cloud.nacos.config.server-addr}")
    private String DEFAULT_SERVER;

    /**
     * 获取配置文件内容config-api
     * @param ipAddr
     * @return
     * @throws NacosException
     * @throws InterruptedException
     */
    @RequestMapping(value = "/configs", method = RequestMethod.GET)
    public Map<String,Object> getConfig(@RequestParam Map<String, Object> params) throws NacosException, InterruptedException {
        Map<String,Object> map = new HashMap<>();
        Map<String,Object> resultMap = new HashMap<>();
        String path = FilePath;
        // 访问nacos
        ConfigService configService = NacosFactory.createConfigService(DEFAULT_SERVER);
        // 通过DataId和Group获取配置文件内容
        String contentInfo = configService.getConfig(DataId,group,1000L);
        // 将配置内容放置到固定的文件中去
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        try
        {
            // 本地调试访问形式
            File distFile = new File(path);
            if (!distFile.getParentFile().exists()) distFile.getParentFile().mkdirs();
            bufferedReader = new BufferedReader(new StringReader(contentInfo));
            bufferedWriter = new BufferedWriter(new FileWriter(distFile));
            char buf[] = new char[1024];         //字符缓冲区
            int len;
            while ((len = bufferedReader.read(buf)) != -1) {
                bufferedWriter.write(buf, 0, len);
            }
            bufferedWriter.flush();
            bufferedReader.close();
            bufferedWriter.close();
            // 重新读取放入配置内容的config文件
            Yaml yaml = new Yaml();
            InputStream yamlFile = new FileInputStream(path);
            // 特殊说明 本地window环境设置编码utf-8,服务器环境设置编码GB2312
            InputStreamReader isr = new InputStreamReader(yamlFile,"GB2312");
            BufferedReader reader = new BufferedReader(isr);
            if(yamlFile != null){
                map = yaml.load(reader);
            }
            // map中即为config.yaml文件内容,按照yaml文件格式封装成json格式
            // 实际业务处理逻辑
            ......
        }catch (Exception e){
            e.printStackTrace();
        }
        return resultMap;
    }
}

2.实现过程中遇到的“坑”

  • 文件路径:博主的项目部署环境是Windows环境,在发布后按照类加载器生成的文件路径在实际生产环境中无法读取。开发环境是在项目Resource目录下生成临时webconfig.yaml文件,在生产环境则涉及到读取jar包外文件路径错误的问题,建议大家可以按照实际的环境定义好临时yaml文件路径或者程序中对获取的文件路径进行处理。
  • 汉字编码:博主的目标yaml文件中存在"#注释",或者value值为汉字的配置信息,导致在读取临时yaml文件是无法序列化的问题// 特殊说明 本地window环境设置编码utf-8,服务器环境设置编码GB2312
    InputStreamReader isr = new InputStreamReader(yamlFile,"GB2312"); BufferedReader reader = new BufferedReader(isr);
    通过此方法来解决汉字无法序列化的问题。

总结

*登山路上的慕码人,理解不透的地方还请各位指点!*
*欢迎大家多多指正交流!*
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

观云卷云舒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值