SpringBoot中application.yaml你不知道的冷知识!

本文讲述了作者帮助一位网友解决SpringBoot应用启动时数据库连接错误的故事,发现问题源于00后程序员配置的数据库密码以0开头,被yaml解析器误认为八进制。作者揭示了解决方案:避免以0开头的数字作为密码,并确保正确引用以防解析器自动转换进制。
摘要由CSDN通过智能技术生成

六月六日夜,解衣欲睡,网友求助让帮忙运行一下自己在Github下载的源码,说是一个SpringBoot的系统,怎么都启动不起来,我心想这不张飞吃豆芽-小菜一碟吗?可是就是这么简单的事情,让我琢磨了近两个小时。最后我总结出是00后程序员用SpringBoot有Bug,斜眼笑,且看下文。

还原现场

先看网友的application.yaml截图,打眼一看,没什么问题,仔细看还是没什么问题。但启动项目报错,提示连接数据库密码错误。

开始尝试解决

首先用命令行登录mysql,验证下本地是否有装mysql,且账号密码是否正确,再验证下链接中的数据库是否存在(虽然没有数据库报的不是这个错)。

结果是:都没有问题。

然后,没办法直接继续看报错日志,发现日志中说jdbcDialectBean创建失败,点进去打上断点看看吧。

image-20230608195508104.png

再启动项目,断点停住了,然后开始查看operations对象的属性,经过一顿乱翻,发现了在operations -> classicJdbcTemplate -> dataSource下存在数据库连接信息。打开一看傻眼了。

账号、驱动、链接都对,怎么你密码变成8533了,我明明配置的是020525啊,为什么?

刚开始我怀疑难道在其他地方配置了数据库信息,没有加载application.yaml中的?但是我全局搜索了8533,无果。然后尝试修改账号为root1,再debug启动。

image-20230608200102810.png

发现账号成功加载到了root1,那说明数据库连接信息就是加载的application.yaml中配置的。那这是为啥呢,小小的脑袋,大大的问号!

随后又尝试修改application.yaml文件,因为这个源码使用的是默认的数据库连接池,所以尝试配置连接池的密码为020525,但是debug启动之后,还是显示8533!!,这时我快疯了。

但是不能放弃,毕竟刚开始可是怀着小菜一碟的心态来的。又开始删刚加的hikari.password配置,再把之前的password还原。习惯使用快捷键的我,再username这一行,使用ctrl + D复制当前行,就是下面这个样子,然后我把下面的username改成password,这是已经不想把password的值改回到020525了,因为已经快崩溃了!其实当你尝试了所有失败的可能之后,你就只剩下了成功!

image-20230608200631245.png

image-20230608200919657.png

再debug启动看看,再看dataSource中加载的数据库配置信息,惊奇的发现,密码加载的是root1,可真是山重水复疑无路,柳暗花明又一村啊。

image-20230608201051159.png

这下就开始想root1020525两个密码的区别,首先一个是纯数字,一个是字母+数字。难道是SpringBoot某个版本的bug,会将数字密码转义掉?但很快排除了这个问题,因为国人在安装MySQL时密码不是123456,就是root,所以纯数字肯定是没有问题的,也修改密码为123456进行了验证,也确实没有问题。

到这,其实大多人就止步于此,毕竟能跑就行,我也是,帮网友修改了数据库root密码,改为root,再修改application.yaml中的密码,再次启动,不出意外,成功启动。关机!睡觉!

但是刚躺倒到床上,心里一直想这个事情,020525123456有啥区别呢(彩蛋:这网友肯定是个00后,而且是5月25的,所以00后用SpringBoot有Bug)。

不睡了,睡什么睡,然后又起床开电脑,准备弄清楚为什么020525加载到datasource里面会变成8533,然后从刚开始打断点的地方往上找,找了很久没一点头绪,人在晚上脑子是真的转不过来。最后才想到,可以从加载application.yaml开始往下找啊,看到底是哪里把020525改成了8533,于此同时也搜索了相关SpringBoot加载application.yaml的相关文档,这里找到一篇18张图,详解SpringBoot解析yml全流程,发现他的情况和我的类似,但是我看源码功底真的太差劲了,跟着他的路径找,最终发现了奥妙之处。

其实就是在解析application.yaml中的配置文件时,SpringBoot引入的是org.yaml:snakeyaml包,当你配置value第一个字符是yaml中规定的特殊字符之后,然后再用特殊字符中所对应的正则表达式进行校验,如果校验不通过,则认为是字符串;如果校验通过,则就会对这个value进行转换了,而我们刚好巧的是,我们的密码第一位是0,所以我们满足了其中一个规则。

继续跟源码,发现,进入了ConstructYamlIntconstruct方法,具体规则如下。

image-20230608204212691.png

因为我们的密码是020525,第一个字符是0,所以被认为我们传入的值是8进制,然后截掉第一位,剩下5位,为20525,后面createNumber就是将八进制20525转为十进制,此时这个020525就加载完成了。

所以就解释了为啥020525变成了最终的8533

image-20230608204528889.png

总结

这个问题的原因就是我们数据库密码是以0开头的,所以被yaml解析器错误的认为我们的value是8进制的,它帮我们转换成了10进制,所以一直导致数据库密码错误,连接失败。

解决方案呢,最简单的就是在application.yaml配置纯数字时,一定要小心,避免0、0b、0x开头,如果非要用,那么一定要在value前后加上单引号,这样yaml解析器就不会帮我们转换进制了。

附录列举了yaml会匹配的第一个字符列表。

附录

image-20230608210039600.png

作者:Ponder
链接:https://juejin.cn/post/7242247549510500408
来源:稀土掘金
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值