起因

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

还原现场

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

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

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

开端测验处理

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

结果是:都没有问题。

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

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

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

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

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

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

刚开端我怀疑难道在其他地方装备了数据库信息,没有加载application.yaml中的?可是我全局查找了8533,无果。然后测验修正账号为root1,再debug发动。

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

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

随后又测验修正application.yaml文件,由于这个源码运用的是默认的数据库连接池,所以测验装备连接池的暗码为020525,可是debug发动之后,仍是显现8533!!,这时我快疯了。

SpringBoot中application.yaml你不知道的冷知识!
可是不能抛弃,究竟刚开端可是怀着小菜一碟的心态来的。又开端删刚加的hikari.password装备,再把之前的password还原。习气运用快捷键的我,再username这一行,运用ctrl + D仿制当前行,便是下面这个样子,然后我把下面的username改成password,这是已经不想把password的值改回到020525了,由于已经快崩溃了!其实当你测验了所有失利的可能之后,你就只剩下了成功!

SpringBoot中application.yaml你不知道的冷知识!
SpringBoot中application.yaml你不知道的冷知识!
再debug发动看看,再看dataSource中加载的数据库装备信息,惊奇的发现,暗码加载的是root1,可真是山重水复疑无路,柳暗花明又一村啊。

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

这下就开端想root1020525两个暗码的差异,首要一个是纯数字,一个是字母+数字。难道是SpringBoot某个版别的bug,会将数字暗码转义掉?但很快排除了这个问题,由于国人在装置MySQL时暗码不是123456,便是root,所以纯数字肯定是没有问题的,也修正暗码为123456进行了验证,也的确没有问题。

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

到这,其实大多人就停步于此,究竟能跑就行,我也是,帮网友修正了数据库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,所以咱们满意了其间一个规矩。

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

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

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

由于咱们的暗码是020525,榜首个字符是0,所以被认为咱们传入的值是8进制,然后截掉榜首位,剩下5位,为20525,后面createNumber便是将八进制20525转为十进制,此时这个020525就加载完成了。

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

所以就解说了为啥020525变成了终究的8533

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

总结

这个问题的原因便是咱们数据库暗码是以0最初的,所以被yaml解析器过错的认为咱们的value是8进制的,它帮咱们转化成了10进制,所以一向导致数据库暗码过错,连接失利。

处理方案呢,最简略的便是在application.yaml装备纯数字时,一定要小心,防止0、0b、0x最初,假如非要用,那么一定要在value前后加上单引号,这样yaml解析器就不会帮咱们转化进制了。

附录列举了yaml会匹配的榜首个字符列表。

附录

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

参考资料

18张图,详解SpringBoot解析yml全流程