首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Mendmix代码解析:百搭的配置文件读取工具ResourceUtils

Mendmix代码解析:百搭的配置文件读取工具ResourceUtils

作者头像
vakinge
发布于 2023-02-22 07:31:32
发布于 2023-02-22 07:31:32
38000
代码可运行
举报
文章被收录于专栏:伯约架构思维伯约架构思维
运行总次数:0
代码可运行

很久很久以前当微服务还没出现、配置中心还没出现、yaml配置文件也还没流行的时候,我们都习惯在项目里面写一个类似ResourceUtils或者PropertiesUtil的工具,无论在静态方法还是jsp代码都屡试不爽。如今Springcloud各种参数化配置、各种profile,Apollo、Nacos各种配置中心以及Properties、Yaml各种配置格式你的配置文件读取工具还好么?接下来我们讲解Mendmix项目的ResourceUtils工具类开启我们Mendmix代码解析系列课程的篇章。

介绍

ResourceUtils贯穿了Mendmix项目各个生命周期,在整个项目中被大量使用。目前支持Properties、Yaml配置文件解析、兼容Springcloud的profile配置方式以及无缝兼容Apollo、Nacos等各种各样的配置中心。同时还提供了诸多快速配置文件读取的方法,如:getListValue,getMapValue、getBeanValue等。

代码分析

加载过程

通过静态代码块加载本地配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static {
   	loadLocalConfigs();
}

loadLocalConfigs这个方法首先尝试获取spring.profiles.active的值,为了兼容通过--spring.profiles.active=prd的方式指定spring.profiles.active的值,Mendmix提供了一个应用启动类基类BaseApplicationStarter,在这个基类里面会处理各种运行参数并把设置为系统变量。

为了兼容本地运行或打包运行提供了loadPropertiesFromFileloadPropertiesFromJarFile两个读取配置的方法,通过这两个方法会把本地的所有 .properties.yaml文件找出来(你也拦不住两种格式的配置文件混用),并建立<文件后缀,[文件名称列表]>的映射关系如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  ".properties" : [ "/.../application-local.properties", "/.../application.properties" ]
}

接下来调用parseSameExtensionFiles方法依次循环解析每个后缀名的配置文件,这个方法做了两件事情:加载所有不带profile的配置文件和找出profile的配置文件。为了确保profile的配置文件能覆盖默认配置,找出的profile的配置文件放在做好放入解析好的所有配置文件Properties里面。这样整个解析过程就完成了。

处理${}引用配置

直接贴代码吧,有点长,类似方法实际上Spring提供的有,仅仅是考虑这只是一个工具类,进来少依赖,所以就自己写了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static String replaceRefValue(Properties properties,String value ) {
		
    	if(!value.contains(PLACEHOLDER_PREFIX)){
    		return value;
    	}
    	
    	String[] segments = value.split("\\$\\{");
		String seg;
		
		StringBuilder finalValue = new StringBuilder();
		for (int i = 0; i < segments.length; i++) {
			seg = StringUtils.trimToNull(segments[i]);
			if(StringUtils.isBlank(seg))continue;
			
			if(seg.contains(PLACEHOLDER_SUFFIX)){	
				String refKey = seg.substring(0, seg.indexOf(PLACEHOLDER_SUFFIX)).trim();
				//其他非${}的占位符如:{{host}}
				String withBraceString = null;
				if(seg.contains("{")){
					withBraceString = seg.substring(seg.indexOf(PLACEHOLDER_SUFFIX)+1);
				}
				
				//如果包含默认值,如:${host:127.0.0.1}
				String defaultValue = null;
				int defaultValSpliterIndex = refKey.indexOf(":");
				if(defaultValSpliterIndex > 0){
					defaultValue = refKey.substring(defaultValSpliterIndex + 1);
					refKey = refKey.substring(0,defaultValSpliterIndex);
				}
				
				String refValue = System.getProperty(refKey);
				if(StringUtils.isBlank(refValue))refValue = System.getenv(refKey);
				if(StringUtils.isBlank(refValue))refValue = properties.getProperty(refKey);
				if(StringUtils.isBlank(refValue)){
					refValue = defaultValue;
				}
				
				if(StringUtils.isBlank(refValue)){
					finalValue.append(PLACEHOLDER_PREFIX + refKey + PLACEHOLDER_SUFFIX);
				}else{
					finalValue.append(refValue);
				}
				
				if(withBraceString != null){
					finalValue.append(withBraceString);
				}else{
					String[] segments2 = seg.split("\\}");
					if(segments2.length == 2){
						finalValue.append(segments2[1]);
					}
				}
			}else{
				finalValue.append(seg);
			}
		}

整合配置中心

考虑到各种各样的配置中心,所以我们不能与具体配置中心产品绑定。所以Mendmix从Spring加载的生命周期下手。在Environment对象加载完成后对所有配置进行一次合并,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static void mergeEnvironmentProperties(){
		MutablePropertySources propertySources = ((ConfigurableEnvironment)environment).getPropertySources();
		
		int count;
		for (PropertySource<?> source : propertySources) {
			if(source.getName().startsWith("servlet") || source.getName().startsWith("system")){
				continue;
			}
			if(source.getName().contains("applicationConfig: [classpath")) {
				continue;
			}
			count = 0;
			if (source instanceof EnumerablePropertySource) {
				for (String name : ((EnumerablePropertySource<?>) source) .getPropertyNames()) {
					Object value = source.getProperty(name);
					if(value != null){
						ResourceUtils.add(name, value.toString());
						count++;
					}
				}
			}
			System.out.println(">>merge PropertySource:" + source.getName() + ",nums:" + count);
		}
	}

该类在com.mendmix.spring.helper.EnvironmentHelper,这里要注意两点:

  1. 确保在应用bean初始化之前完成合并
  2. 要跳过本地配置合并,否则可能出现远程配置又本本地配置覆盖的情况。

用法举例

假如有一份这样的配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
whitelist.ips=10.1.1.10;10.1.1.100
#aliyun OSS
mendmix.cos.adapter.type=aliyun
mendmix.cos.adapter.accessKey=5tHzzxhTs45tbUrKgTHYxxxx
mendmix.cos.adapter.secretKey=aIDWMP2pbvFjML7tYAzfPXXXXXXX
mendmix.cos.adapter.regionName=cn-guangzhou
#feign代理
mendmix.loadbalancer.customize.mapping[mendmix-user-svc]=http://127.0.0.1:8081
mendmix.loadbalancer.customize.mapping[mendmix-order-svc]=http://127.0.0.1:8082

部分用法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//查询指定前缀的配置
Properties properties = ResourceUtils.getAllProperties("mendmix.cos.adapter");
//查询指定前缀并返回对象
CosConfig cosConfig = ResourceUtils.getBean("mendmix.cos.adapter", CosConfig.class);
//KV格式的配置
Map<String, String> mappingValues = ResourceUtils.getMappingValues("mendmix.loadbalancer.customize.mapping");
//返回列表
List<String>  whitelistIps = ResourceUtils.getList(" whitelist.ips");
//	多个配置兼容
ResourceUtils.getAnyProperty("key1","key2");

关于Mendmix

Mendmix基于Apache 2.0开源协议,100%开源。定位是一站式分布式开发架构开源解决方案及云原生架构技术底座。Mendmix提供了数据库、缓存、消息中间件、分布式定时任务、安全框架、网关以及主流产商云服务快速集成能力。基于Mendmix可以不用关注技术细节快速搭建高并发高可用基于微服务的分布式架构。

项目地址:github,gitee

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=jojc0rdfpnkp

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
springboot实战之读取自定义配置文件
我们在开发springboot的项目过程中,为了不把所有的配置信息全都写在application.(yml/properties)中,我们需要自定义配置文件比如common.properties,那么问题来了,我们要如何读取common.properties里面的内容。
lyb-geek
2019/08/06
8.9K0
SpringBoot系列-配置解析
在日常的开发和运维过程中,可以说配置都是及其重要的,因为它可能影响到应用的正常启动或者正常运行。相信在之前 Spring xml 时代,很多人都会被一堆 xml 配置折腾的够呛,除此之外,还有像数据库连接配置、缓存配置、注册中心配置、消息配置等等,这些相信大家都不会陌生。
安徽开发者圈
2020/03/02
1.3K0
【死磕 Spring】---- Spring 的环境&amp;属性:PropertySource、Environment、Profile
spring.profiles.active 和 @Profile 这两个我相信各位都熟悉吧,主要功能是可以实现不同环境下(开发、测试、生产)参数配置的切换。其实关于环境的切换,小编在博客 【死磕Spring】----- IOC 之 PropertyPlaceholderConfigurer 的应用 已经介绍了利用 PropertyPlaceholderConfigurer 来实现动态切换配置环境,当然这种方法需要我们自己实现,有点儿麻烦。但是对于这种非常实际的需求,Spring 怎么可能没有提供呢?下面小编就问题来对 Spring 的环境 & 属性来做一个分析说明。
用户1655470
2019/03/06
2.9K0
【死磕 Spring】---- Spring 的环境&amp;属性:PropertySource、Environment、Profile
springboot 项目读取默认配置
配置文件中有对应key-value的配置时,则读取配置文件中的配置,如果没有对应的key-value时则读取默认的配置
六月的雨在Tencent
2024/03/28
1770
掌握Spring Environment:配置管理的关键
在软件开发中,配置管理是一个关键的部分。无论你的应用程序是运行在开发环境、测试环境还是生产环境,都需要正确配置以确保一切顺利运行。Spring Environment抽象就像是一个神奇的工具箱,它能够帮助你轻松地管理不同环境的配置,并让你的应用程序变得更加灵活。让我们一起探索这个魔法世界的背后,了解如何使用Spring Environment抽象来简化配置管理。
一只牛博
2025/05/30
1140
掌握Spring Environment:配置管理的关键
关于Spring属性处理器PropertyResolver以及应用运行环境Environment的深度分析,强大的StringValueResolver使用和解析【享学Spring】
若直接提PropertyResolver或者StringValueResolver可能很小伙伴会觉得非常的陌生,但是我若提Environment和EmbeddedValueResolverAware这个感知接口,相信大部分小伙伴就能感受到一种亲切感了~。
YourBatman
2019/09/03
6.5K0
关于Spring属性处理器PropertyResolver以及应用运行环境Environment的深度分析,强大的StringValueResolver使用和解析【享学Spring】
SpringBoot如何加载jar包外面的配置文件?
虽然现在springboot提供了多环境的支持,但是通常修改一下配置文件,都需要重新打包。
xjjdog
2020/02/17
1.9K0
Nacos 配置中心源码分析
本文主要和大家一起以源码的角度来分析 Nacos 配置中心的配置信息获取,以及配置信息动态同步的过程和原理。环境介绍和使用 环境介绍:
没有故事的陈师傅
2021/08/13
1.1K0
SpringBoot中如何加载远程配置
本文章将通过结合consul config来讲解在springboot中如何加载远程配置:通过consul config加载consul server中存储的配置。
tunsuy
2022/10/27
1.6K0
nacos配置中心 服务启动的配置加载
Spring抽象了一个environment表示Spring应用程序环境配置,整合了各种各样的外部环境,并提供统一访问的方法getProperty()
周杰伦本人
2022/10/25
1.5K0
Spring Boot 配置文件中的花样,看这一篇足矣!
在快速入门一节中,我们轻松的实现了一个简单的RESTful API应用,体验了一下Spring Boot给我们带来的诸多优点,我们用非常少的代码量就成功的实现了一个Web应用,这是传统的Spring应用无法办到的,虽然我们在实现Controller时用到的代码是一样的,但是在配置方面,相信大家也注意到了,在上面的例子中,除了Maven的配置之后,就没有引入任何的配置。
程序猿DD
2019/07/08
9660
聊聊Spring的环境抽象Environment,以及配置@Profile使用详解(介绍profile的6种激活方式)【享学Spring】
在我刚入行不久时,总是对上下文(Context)、环境(Environment)这类抽象概念搞不清楚、弄不明白、玩不转,更是不懂它哥俩的区别或者说是联系(说实话从中文上来说不好区分,至少我是这么认为的)。 直到现在,我可以根据自己的理解对这两者下个通俗易懂的定义(不喜勿喷):
YourBatman
2019/09/03
2.8K0
聊聊Spring的环境抽象Environment,以及配置@Profile使用详解(介绍profile的6种激活方式)【享学Spring】
Spring中PropertySource属性源配置文件的优先级、顺序问题大解析(加载流程)【享学Spring】
关于Spring的配置文件的优先级、加载顺序一直是个老生常谈的问题。但即使经常被提起,却还是经常被忘记或者弄混。有一种听了很多道理但仍过不好这一生的赶脚有木有。
YourBatman
2019/09/03
7.7K0
Spring中PropertySource属性源配置文件的优先级、顺序问题大解析(加载流程)【享学Spring】
为什么 @Value 可以获取配置中心的值?
由 AutowiredAnnotationBeanPostProcessor 负责来处理 @Value ,此外该类还负责处理 @Autowired 和 @Inject。
Coder小黑
2020/11/25
2.3K0
为什么 @Value 可以获取配置中心的值?
springboot 自定义配置文件加密规则
一般情况下,我们做项目的时候,中间件例如mysql,redis, zk 的账号密码一般都是写在配置文件里面的, 这样代码泄露的情况下, 就很不安全。
分享干货的你
2021/04/23
1.2K0
用 @Value(“${xxxx}“)注解从配置文件读取值的用法
2. 在spring的配置文件中加载配置文件dbconfig.properties :
微风-- 轻许--
2022/04/13
1K0
Spring Boot属性配置文件详解
相信很多人选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能,还能实现快速开发的便捷。我们在Spring Boot使用过程中,最直观的感受就是没有了原来自己整合Spring应用时繁多的XML配置内容,替代它的是在 pom.xml中引入模块化的 StarterPOMs,其中各个模块都有自己的默认配置,所以如果不是特殊应用场景,就只需要在 application.properties中完成一些属性配置就能开启各模块的应用。 在之前的各篇文章中都有提及关于 application.proper
程序猿DD
2018/02/01
1.2K0
java如何指定外部的配置文件
工作当中很多时候都希望可以把配置文件外放,这样的话就可以做到配置与业务分离,其实有很多种放式,比如xml,properties,这里就说一下如何用properties做到配置文件跟业务代码的分离
shengjk1
2018/10/24
4.6K0
SpringCloud入门之常用的配置文件 application.yml和 bootstrap.yml区别
SpringBoot默认支持properties和YAML两种格式的配置文件。前者格式简单,但是只支持键值对。如果需要表达列表,最好使用YAML格式。SpringBoot支持自动加载约定名称的配置文件,例如application.yml。如果是自定义名称的配置文件,就要另找方法了。可惜的是,不像前者有@PropertySource这样方便的加载方式,后者的加载必须借助编码逻辑来实现。
jack.yang
2025/04/05
3740
Springboot多个配置文件的实现
配置文件名需要满足application-{profile}.properties的格式。 {profile}对应的是环境标识,比如:
Cheng_Blog
2022/02/25
2.1K0
推荐阅读
相关推荐
springboot实战之读取自定义配置文件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档