【Java项目】SpringBoot项目如何从自研配置中心拉取配置

news2024/11/16 23:48:00

文章目录

  • 前言
  • 思路

前言

先简单说一下这个题目的意思是什么。

我们知道,如果我们的项目是SpringCloud的项目,我们是可以把我们的本地配置写到云端的的配置中心的,比如集成SpringCloud Alibaba,你就可以使用Nacos,然后把配置写到Nacos中,从而保证配置的安全。

那么如果是SpringBoot项目,大部分我们的配置都是直接写在本地的,那么就会出现代码如果泄露,配置文件内的内容就会被发现从而造成危险,所以如果可以把SpringBoot项目的配置文件也从云端或者远程处拉取的话,那么项目的安全度就会高很多。

所以可以考虑使用一种类似于配置中心的方式,我们自己建设一个简易的配置中心,然后我们发送HTTP请求去配置中心拉取代码,也可以做到配置不存在本地的形式。

我的思路是,写一个小网页,然后把配置存储在网页对应的数据库中,也就是我们写一个内部人员使用的管理系统,我们可以把配置输入到这个管理系统中,和Nacos差不多。

然后我们只需要向管理系统发送请求,并且携带上一些参数,配置系统就会把其中的配置返回给我们,从而做到SpringBoot项目也可以从远程拉取配置的方式。

思路

我们公司的实现方式是,封装好一个jar包,打包到maven仓库,之后只要项目需要使用,就拉取这个项目即可。

之后就是,我们得配置我们需要加载的一些配置信息,以及提供一些项目参数来确定能从配置中心拉取到唯一的配置。比如提供项目的id,项目的开发环境env,需要加载的一些其他需要从配置中心拉取的配置。

配置有了,我们需要在我们的jar包中,封装好一些读取用户本地配置的一些信息,也就是我们需要读取用户本地的配置文件,我们先开发一个类用于存储最终得到的信息:

public class AppProperties {
    //默认开发组
    private static final String DEFAULT_GROUP = "Default";
    private static String projectName;//项目名称
    private static String environment;//开发环境
    private static String group;//开发组

    public AppProperties() {
    }

    public static String getGroup() {
        return group;
    }

    public static String getAppName() {
        return projectName;
    }

    public static String getEnvironment() {
        return environment;
    }
}

之后,我们就得编写一个类,这个类需要用于获取用户可能的存放配置文件的所有地方,可以分为如下几种:ClassPath、System、UserDir、Environment。

public class ConfigCenterClientEnvironment {
    private List<Property> propertySourcesList = new CopyOnWriteArrayList();

    public ConfigCenterClientEnvironment() {
        this.propertySourcesList.add(new EnvironmentProperty());
        this.propertySourcesList.add(new SystemProperty());
        this.propertySourcesList.add(new UserDirProperty());
        this.propertySourcesList.add(new ClassPathProperty());
    }

    private String getByOrder(String name) {
        Iterator i$ = this.propertySourcesList.iterator();

        String value;
        do {
            if (!i$.hasNext()) {
                return null;
            }

            Property propertySources = (Property)i$.next();
            value = (String)propertySources.get(name);
        } while(!StringUtils.isNotBlank(value));

        return value;
    }

    public String getEnvironment() {
        return this.getByOrder("environment");
    }

    public String getProjectName() {
        return this.getByOrder("projectName");
    }

    public String getGroup() {
        return this.getByOrder("group");
    }
}

下面简单的贴出一个获取System配置的类

public class SystemProperty extends Properties {
    public SystemProperty() {
        String projectName = System.getProperty("projectName");
        String environment = System.getProperty("environment");
        String group = System.getProperty("group");
        if (StringUtils.isNotBlank(projectName)) {
            this.put("projectName", projectName);
        }

        if (StringUtils.isNotBlank(environment)) {
            this.put("environment", environment);
        }

        if (StringUtils.isNotBlank(group)) {
            this.put("group", group);
        }

    }
}

类似于从ClassPath获取配置的方式也一样,只不过获取配置文件的方式变为了先使用InputStream流去读取配置文件,读取到配置文件非空之后在读取配置文件中对应的配置。

ok,到目前位置我们已经把本地的配置文件全都读取完毕并且保存好了,只好我们要做的就是基于这些配置文件的信息,向我们的注册中心发送请求,并且从注册中心得到数据。

大概的代码编写方式如下,我们传入对应的projectName,env,group等参数,然后我们使用这些参数配合上我们注册中心的地址,比如http://xxx/xxx/然后加上我们的这些参数拼接在后面,就可以得到一个完整的url串。这里你也可以按照上面一样的方式,让配置中心的地址也选择从我们本地读,但是这样子不太好了,就失去了我们一开始配置这个东西的理由。
得到url之后,我们发送这个url向注册中心,并且得到一个json串。

	private List<ProjectConfig> getProjectConfigListFromRemote(String projectName, String env, String group) {
        try {
            String url = UrlBuilder.getConfigListByEnv(projectName, env, group);
            String json = this.httpHelper.get(url);
            this.currentStatus = "ready"; //当前是否被好发送
            return JsonHelper.convertToProjectConfig(json);
        } catch (Exception var6) {
            this.currentStatus = "offline"; //配置中心离线 报错
            logger.error(var6.getMessage(), var6);
            throw new RuntimeException(var6.getMessage(), var6);
        }
    }

当然,为了确保当前用户拥有获取配置的权限,我们还可以加上一个用户校验。

class HttpHelper {
    private String user;
    private String password;

    public HttpHelper(String user, String password) {
        this.user = user;
        this.password = password;
    }

    public String get(String url) throws Exception {
        return this.HttpInvoker(url, "GET", this.user, this.password, (String)null);
    }

    public String post(String url, String body) throws Exception {
        return this.HttpInvoker(url, "POST", this.user, this.password, body);
    }
    }

然后,我们通过Json解析的方式,将从配置中心得到的配置,进行Json的解析,得到最后的类,我们可以使用gson进行解析
在这里插入图片描述
gson解析后如下
在这里插入图片描述
至此,我们已经把配置从配置中心获取到了,至于获取到的配置的格式,是你自己定义的,只要方便你之后进行解析即可,我们使用的是xml的配置。
在得到了配置之后,如果我们需要使用这些配置对本地的一些类进行配置,那么我们直接根据配置的key获取到配置对应的value即可,然后解析value这个字符串,然后对属性与类进行赋值即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/712828.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

科技云报道:智能化潮起,物联网产业链安全和效率问题何解?

科技云报道原创。 黑灯瞎火的夜。一胖一瘦两个小伙分别拿着平板和手机&#xff0c;在某知名新能源汽车周围鬼鬼祟祟地打转。 不到一分钟的时间&#xff0c;其中的瘦小伙很轻易地就用手机解开了车门锁。另外一名胖小伙&#xff0c;却用了两分钟&#xff0c;花了老大的力气&…

网站建设如何快速建站_网站建设快速建站有哪些方法

网站建设快速建站方法 1、JavaScript 压缩和模块打包 JavaScript 应用是以源码形式进行分发的&#xff0c;而源码解析的效率是要比字节码低的。对于一小段脚本来说&#xff0c;区别可以忽略不计。但是对于更大型的应用&#xff0c;脚本的大小会对应用启动时间有着负面的影响。…

dubbo Sentinet 限流 流控配置 高级 直连 关联 链路 预热冷启动 排队等待 单机 qps 并发 机器总体法制 单机均摊 集群俩种身份

目录 进入配置 单机超过10个限流 Qps 和 并发线程数区别使用思路 集群阈值模式 单机均摊 总体阈值 集群流控中共有两种身份&#xff1a; 高级-流控模式 直连 关联 链路 首先在实现类上加注解 Warm Up 预热冷启动 10秒内完成 100 预热并发效果 效果 排队等待 单…

Linux11.进程等待

1.写时拷贝 :使用fork创建子进程的时候&#xff0c;操作系统使用写时拷贝&#xff0c;类似于浅拷贝和深拷贝&#xff0c;对于只读的数据进行浅拷贝&#xff0c;对于需要写入的数据进行深拷贝。 2.cpu中有一个EIP寄存器&#xff0c;也叫pc指针(程序计数器)&#xff0c;永远指向…

【ARM】-数据访问中止异常中断处理程序的返回

文章目录 处理流程示例 处理流程 当发生数据访问中止异常中断时&#xff0c;程序要返回到该有问题的数据指令处&#xff0c;重新访问该数据。因此数据访问中止异常中断程序应该返回到该数据访问中止异常中断的指令处&#xff0c;而不是像前面两种情况下返回到发生中断的指令的…

SpringBoot实战项目整合RabbitMQ+ElaticSearch实现SKU上下架功能

文章目录 前言1、前置条件2、搭建service-search模块3、开发功能接口3.1 添加远程调用方法3.2、创建远程调用模块3.3、开发service-search 模块接口 4、RabbitMQ5、完善SKU管理商品上下架5.1、商品服务5.2、es服务 6、最终测试总结 前言 最终实现效果&#xff1a;针对SKU的上下…

Java基础---String、StringBuilder和StringBuffer的区别

目录 典型回答 String的""是如何实现的 StringBuffer和StringBuilder 不要在for循环中使用拼接字符串 典型回答 本质上都是char[]字符数组的实现在Java9之后&#xff0c;String类的实现改用byte数组存储字符串使用final关键字修饰字符数组来保存字符串&#xff0…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)四:用户注册界面及对应功能实现

一、本章内容 本章实现用户注册功能,包括短信注册界面、邮箱注册界面、短信注册修改接口、邮箱注册修改接口等相关内容,实现用户注册的完整流程。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频 基于VUE3+Layui从头搭建通用后台管理系统合…

打造 API 接口的堡垒

前言 伴随互联网革命快速创新发展&#xff0c;API 需求的日益剧增&#xff0c;针对 API 的攻击几乎遍布各个行业&#xff0c;据报道 2022 年全年平均每月遭受攻击的 API 数量超过 21 万&#xff0c;游戏、社交、电商、制造等行业依然是攻击者主要目标。例如社交软件某特&#…

cuda优化

希望用GPU解决更大的问题&#xff0c;更多的程序在同等的设备商运行 最大化单个kernel的运算强度&#xff0c; 最小化内存的操作时间 在第一步分析的时候&#xff0c;不要依赖直觉 类似CPU&#xff0c;单个线程处理这个事情&#xff0c;串行 把读取全局内存的地方合并以后…

7.2 文件系统的简单操作

7.2.1 磁盘与目录的容量 磁盘的整体数据是在superblock区块中&#xff0c;但是每个个别文件的容量在inode当中记载的。 df&#xff1a;列出文件系统的整体磁盘使用量&#xff1b; du&#xff1a;评估文件系统的磁盘使用量&#xff08;常用在推估目录所占容量&#xff09; d…

Postman是个好用的工具,不试一下?

忘了 postman 是被谁种草的&#xff0c;很长一段时间内 postman 都是我做接口测试的首选工具&#xff0c;之前也有小伙伴跟我安利过 IDEA 中的 RestfulToolkit 插件&#xff0c;但是一直没机会体验&#xff0c;最近抽空玩了一把&#xff0c;感觉在某些场景下还蛮不错的(不需要认…

互联网SaaS产品的账户体系应该如何设计-账户分析

在进行账户体系设计之前&#xff0c;需要先理清产品使用群体、付费群体&#xff0c;这两个统称为用户群体&#xff0c;还需要了解产品的使用场景、产品功能以及产品的商业模式。从产品战略顶层进行SaaS产品的用户体系设计。 我们首先对人的本质和价值进行深入的分析&#xff1b…

你的测试技术这么烂,不学几招怎么跳槽?

最近几年我一直担任着软件测试面试官的角色&#xff0c;正好过年回来&#xff0c;马上就要金三银四求职季了&#xff0c;所以想写点面试的经验分享给大家&#xff0c;希望能对大家有些帮助。碍于才疏学浅&#xff0c;又是理工出身&#xff0c;字里行间未免词不达意&#xff0c;…

ubuntu20.04 使用pip安装配置Pytorch

关于pytorch的安装&#xff0c;我之前其实写过一篇博客&#xff1a;解决问题&#xff1a;import torch失败和torch.cuda.is_available()返回false 但是那是在windows下的&#xff0c;在ubuntu双系统下好像情况有点不一样&#xff0c;但是所幸踩的坑不算多&#xff0c;这里总结如…

2023全云在线联合微软AIGC专场沙龙:人工智能与企业创新,促进创造力的数字化转型

6月29日&#xff0c;由全云在线平台和微软联合主办的人工智能与企业创新&#xff1a;促进创造力的数字化转型——2023AIGC微软专场沙龙在广州天河区正佳万豪酒店举行。 关于2023AIGC微软专场沙龙 GPT翻开了AGI新的一页&#xff0c;也翻开了各行各业的新篇章。 2022年11月30日…

当心僵尸:过时Linux内核的安全风险

导读设备年年新&#xff0c;内核永不换。早该被淘汰的Linux内核版本&#xff0c;依然阴魂不散地扎根在各种各样的设备中&#xff0c;驱动着这些设备如同《行尸走肉》的丧尸游荡在世界各地。 Linux内核安全漏洞是新闻头条常客。最近又有一个隐身十年之久的严重内核漏洞被曝光了…

layer做阻塞式弹出层的方法

今天遇到一个问题&#xff1a;文章来源地址https://www.yii666.com/article/301050.html?actiononAll layer弹出一个confirm提示窗&#xff0c;然后confirm还没有点击对应的按钮的时候&#xff0c;就已经执行了后续代码&#xff0c;我这里做出的判断是&#xff0c;是否需要进行…

vue新特性

vue3 ref、reactive toRefs setup ref reactive 实现了数据响应式&#xff0c;不能使用 ES6 解构&#xff0c;会消除响应特性。所以需要 toRefs 解构&#xff0c;使用时&#xff0c;需要先引入。 let me reactive({single:true,want:"暖的像火炉的暖男" }) //运…

小黑收到阿黄宴请潮汕牛肉火锅,跟淹哥包鹏拉面,明日飞新疆乌鲁木齐地窝堡的leetcode之旅:剑指 Offer II 016. 不含重复字符的最长子字符串

小黑代码&#xff08;与官方题解思路一致&#xff09; class Solution:def lengthOfLongestSubstring(self, s: str) -> int:# 字符串长度n len(s)# 定义双指针head 0tail 0# 窗口集合set_ set()# 结果变量result 0while tail < n:# 该字符不在集合里if s[tail] no…