问题

在项目中时常需要读取配置文件,例如某个变量会随着环境的不同而不同,在springboot项目中会很容易想到yml的方式。但是最近遇到一个问题,发现下划线被注入的到bean中会丢失下划线,差点引起线上故障,demo如下:

@Component
public class YmlConfTest {@Value("${id}")private String id;
}

yml配置文件如下:

id : 1_2

实际运行中发现id注入的是12,而不是预期的1_2,这就导致问题发生。

原因分析

习惯性的在网上简单搜索了一下问题,发现很少有描述这个问题的,偶尔几篇说key不能有下划线,但我是value下划线的问题,因此也不是很满意,于是有了这篇文章帮助需要的人,所以本文打算分析为什么会丢失掉下划线,以下非核心逻辑简单描述感兴趣可以自行查阅,重点描述下划线丢失的逻辑。

spring部分
  1. Spring容器在加载的时候会有事件通知触发相关的监听器Listener逻辑,yml加载就在其中的 ConfigFileApplicationListener
  2. 监听器经过一系列寻址找到对应的配置文件
  3. 如果是yml配置文件会找到YamlPropertySourceLoader进行加载配置文件
yml部分
  1. 最终遍历到配置项的节点,org.yaml.snakeyaml.resolver.Resolver进行key和value的解析任务
    public Tag resolve(NodeId kind, String value, boolean implicit) {if (kind == NodeId.scalar && implicit) {final List<ResolverTuple> resolvers;if (value.length() == 0) {resolvers = yamlImplicitResolvers.get('\0');} else {// 获取字符串第一个字符,并获取对应的类型// yamlImplicitResolvers保持了所有ASCII码和对应的可解析工具的列表。resolvers = yamlImplicitResolvers.get(value.charAt(0));}// 获取到"1_2"中"1"的解析工具有两个,分别是整型和浮点两个解析工具if (resolvers != null) {// 遍历这两个解析类for (ResolverTuple v : resolvers) {Tag tag = v.getTag();// 整型的正则匹配 Pattern regexp = v.getRegexp();// 常量表达式Pattern.compile("^(?:[-+]?0b[0-1_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[0-9a-fA-F_]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$");if (regexp.matcher(value).matches()) {// 匹配成功,返回目标类型为int的tagreturn tag;}}}// ...}//...}

这里用正则匹配的方式把这个value的的tag标记为int的解析目标后,进行后续的把其转换为基本类型:

    protected Object constructObjectNoCheck(Node node) {// ...// 获取对应的值解析工具,就是根据tag获取对应的转换工具Construct constructor = getConstructor(node);Object data = (constructedObjects.containsKey(node)) ? constructedObjects.get(node): constructor.construct(node);finalizeConstruction(node, data);constructedObjects.put(node, data);recursiveObjects.remove(node);if (node.isTwoStepsConstruction()) {constructor.construct2ndStep(node, data);}return data;}


匹配到了ConstructYamlInt之后:

    public class ConstructYamlInt extends AbstractConstruct {@Overridepublic Object construct(Node node) {// 第一步就是把下划线替换掉String value = constructScalar((ScalarNode) node).toString().replaceAll("_", "");// ...}}

这里下划线就没了,后续就转换为了12。

解决方案

根据源码实现,只要给配置的值加双引号即可识别为字符串。

总结

在追踪问题根源的过程也是欣赏学习源码设计模式与代码风格的过程。框架的确是个好东西,但是理解的不到位,很多细节也是有很多坑。

yml读取下划线丢失问题相关推荐

  1. 带下划线的二级域名IE无法读取session

    带下划线的二级域名, IE无法读取session和cookie, firefox/chrome等都可以. 域名规范中确实不允许有下划线. RFC 952明确规定"A "name&q ...

  2. Java 读取 Word文档的字体、字号、文字颜色、文字背景、文字是否加粗或倾斜、文字下划线、段落等属性

    Work库:free spire.doc.jar 3.9.0 由于这个包比较大,maven依赖容易下载失败,故此提供百度云下载地址,下载地址在最下面         可支持读取字体.字号.文字颜色.文 ...

  3. 字段和字段的参数,查询的13个方法,但标的双下划线外键和多对多操作

    字段 常用字段  AutoField() 自增列,必须填入参数 primary_key=True则成为数据库的主键.无该字段时,django自动创建 一个model不能有两个AutoField字段. ...

  4. Spring Boot——MyBatis配置带下划线命名的字段自动转换驼峰命名解决方案

    问题描述 MyBatis无法查询出属性名和数据库字段名不完全相同的数据. 即:属性名和数据库字段名分别为驼峰命名和下划线命名时查出的数据为NULL. 问题分析 MyBatis默认是属性名和数据库字段名 ...

  5. Python中单个下划线“_”变量的目的是什么?

    在Python中,下划线_被视为" 我不关心 "或" 丢失 "变量 python解释器将最后一个表达式值存储到名为的特殊变量中_. >>> 1 ...

  6. C语言中的标识符以字母或下划线开头,牛逼大神整理的C语言基础知识,你确定你不码下来?...

    [[怪兽爱C语言]牛逼大神整理的C语言基础知识,你确定你不码下来?]https://toutiao.com/group/6577344220355363341/?iid=15906422033& ...

  7. linux vi 出现下划线,Vim高亮当前行(显示为下划线)的解决方案

    最近配置Vim,由于以前的vimrc早已丢失,只好重新配置一份,此为题外话,略过不提- 在Vim中,可以选择开启高亮当前行,这是一个很不错的特性.开启它也很简单,只需要在vimrc中加入这么一行: 1 ...

  8. VBA实现数据库中的字段处理(下划线去掉,后面的字母变大写)之版本1.1。

    2020 / 06 /08 以前的文章,修改了一下,代码格式全废了... 1.0版本中有两个问题,现在已经修正了 '履历 '2010/10/23(周六)下午第一版做成 '2010/10/26(周二)晚 ...

  9. VBA实现数据库中的字段处理(下划线去掉,后面的字母变大写)之版本1.0。

    可以处理一列数据,数据从B6位置开始,中间不能有空,遇到空就判断到了最后一个,跳出循环! 1.0版本中有两个问题,现在已经修正了 '履历 '2010/10/23(周六)下午第一版做成 '2010/10 ...

最新文章

  1. 麦芒8能安装鸿蒙系统吗,首颗5G基带芯片麦芒8发布鸿蒙最新进展
  2. 聊一聊 Redis 数据内部存储使用到的数据结构
  3. 脚本自动实现DNS服务各区域配置文件
  4. 设计模式之_Iterator_04
  5. CTF中遇到不知道文件类型_AE中你不知道的隐藏功能-Mask与特效
  6. java.net.SocketException: Software caused connection abort: socket write erro
  7. 【python】生成器
  8. java的多重循环实现杨辉三角_java使用for循环输出杨辉三角
  9. html样式超出出现滚动条,CSS 设置的高度超出屏幕高度为什么没出现滚动条?
  10. rtl驱动 ubuntu 禁用_【Ubuntu】UEFI安装Windows 10和Ubuntu 18.04双系统(深度爬坑)
  11. python可视化经纬度信息
  12. asp.net mvc3 简单的文件上传下载
  13. 平面向量内积坐标公式推导_向量内积的坐标表示.ppt
  14. 如何在word中输入带对号的方框
  15. 神仙打架!2020年清华大学本科生特奖答辩入围名单公布!简历爆棚!
  16. 成为会带团队的技术人 大项目:把握关键点,谋定而后动
  17. 【ETL】一个故事知道ETL是什么
  18. JavaScript数据类型及转换
  19. [智能硬件]是什么?智能硬件应用领域包括哪些?
  20. JZOJ100029 陪审团

热门文章

  1. Fortify Access Control
  2. Java实现点分十进制IP和长整型转换
  3. 怪”博士闵万里:用人工智能,解决吃饭出行问题
  4. 输入起始日期,截止日期,查询天数
  5. 假如有人欺骗了你•••
  6. 文本挖掘技术——引言
  7. 网站安全防护与漏洞扫描的关系
  8. c++读取yolov5模型进行目标检测(读取摄像头实时监测)
  9. 计算机班级学情分析报告,班级学习情况中期总结
  10. python strftime 中文_strftime(python)问题