SpringBoot2.x升级踩坑--新增Configuration property name限制
最近公司项目在做SpringBoot的升级,在升级过程中遇到了一些问题,简单记录一下,做个分享。另外,本文中的程序只为示例代码,并非公司生产环境代码。
遇到什么问题
从SpringBoot1.x升级到SpringBoot2.x之后,解决完编译异常,运行程序,在程序启动时报错:
报错信息就已经很直白的告诉了我们错误原因:
配置属性名称“com_shen”无效
无效字符: '_', 原因:规范名称应为kebab-case(用'-'分隔),小写字母数字字符,并且必须以字母开头
怎么解决
经过排查,是因为在
application.properties文件中有如下一个配置项:
com_shen.name=xiaohei
对应Java程序代码:
@Getter @Setter @ConfigurationProperties(prefix = "com_shen") public class Service { private String name; }
结合报错日志,我们可以很容易的解决这个问题,去掉配置项中的
_,将配置项name修改为
com.shen.name即可。
源码解析
你以为文章写到这里就结束了吗?其实并没有。hhhhhh,通过这个问题,我们来看一下SpringBoot2.x的内部源码。什么,你不知道该从哪里入手来看这个源码,没关系,我们一步一步来。
点开
@ConfigurationProperties源码,
在Spring中,大量的功能都是通过
BeanPostProcessor来实现的。而且,Spring中的源码注释写的非常的仔细。通过源码注释我们可以猜到可能是
ConfigurationPropertiesBindingPostProcessor这个类在负责
@ConfigurationProperties注解的背后支持。
点开
ConfigurationPropertiesBindingPostProcessor类源码,发现在该类中Override了
BeanPostProcessor的
postProcessBeforeInitialization方法:
在这个方法中,调用了
bind(bean, beanName, annotation);方法。这个方法名叫"绑定",方法中传入了bean、beanName和annotation的信息,经验告诉我这个方法大概率就是在负责解析
@ConfigurationProperties,进行属性绑定。
于是,在这里打一个条件断点,debug运行项目:
通过debug发现的确是这个方法在进行属性绑定。而且底层调用了
org.springframework.boot.context.properties.bind.Binder#bind(String, Bindable<T>, BindHandler)方法:
在这个
bind方法中,又调用了另一个方法
bind(ConfigurationPropertyName.of(name), target, handler);,而且通过
name生成了
ConfigurationPropertyName对象
ConfigurationPropertyName.of(name),通过方法名我们可以猜测,这个方法可能是在负责解析Configuration Property Name,项目启动的报错信息很有可能是这个方法中抛出的。点开源码:
发现在这个方法中,调用了
InvalidConfigurationPropertyNameException.throwIfHasInvalidChars(name,ElementValidator.getInvalidChars(elementValue));。Spring代码命名真的是太优雅了,虽然名称很长,但是让源码阅读者一看就能明白这个方法在做什么。
通过源码,我们可以看到,在SpringBoot中对Configuration property name中的字符进行了有效性的判断,判断规则如上图所示。
ElementValidator类是
ConfigurationPropertyName的一个内部类。
ConfigurationPropertyName是SpringBoot2.0新增的一个类,让我们一起来阅读一下类中注释,了解一下这个类:
机器翻译结果如下:
由点分隔的元素组成的配置属性名称。 用户创建的名称可以包含字符“ a-z”,“ 0-9”)和“-”,它们必须为小写字母,并且必须以字母数字字符开头。 “-”仅用于格式化,即“ foo-bar”和“ foobar”被认为是等效的。
“ [”和“]”字符可用于表示关联索引(即Map键或Collection索引。索引名称不受限制,并且区分大小写。以下是一些典型示例:
spring.main.banner-mode
server.hosts [0]。名称
日志[org.springboot] .level
使用@Value
我们知道,SpringBoot中除了可以使用
@ConfigurationProperties之外,还可以使用
@Value。
Demo程序如下:
@Getter @Setter @Component public class Service { @Value("${com_shen.name}") private String name; }
application.properties文件:
com_shen.name=xiaohei
在这种情况下,项目依旧启动成功了,而且成功的获取到了
com_shen.name的属性值。也就是说,
@Value注解中并没有表达式做限制。
拓展阅读
Property Binding in Spring Boot 2.0 : https://spring.io/blog/2018/03/28/property-binding-in-spring-boot-2-0
欢迎关注公众号,大家一起学习成长。
- SpringBoot2中配置文件的调整,升级SpringBoot2时候注意的坑
- pip从8升级到18的错误:from pip import main ImportError: cannot import name 'main'
- Silverlight for Windows Phone Toolkit升级 新增四个控件
- 升级android sdk到5.0时,创建项目出现错误:No resource found that matches the given name 'android:Widget.Material.A
- Greendao 3.X 数据库升级,新增int、long数据类型字段NOT NULL 解决方案
- WinXP升级到SP2后网卡获取不到IP受限制或无连接
- Silverlight for Windows Phone Toolkit升级 新增四个控件 推荐
- 升级到AndroidStudio3.0 之后的遇到问题的处理(新建、方法数限制等)
- dotConnect for Oracle 更新至v9.2,新增程序集添加复选框,EF支持升级|附下载
- Visual Studio 2008 破解90天限制的激活升级方法!
- Silverlight for Windows Phone Toolkit升级 新增四个控件
- 实测各浏览器cookie的name个数及最大容量限制
- XCODE升级到7.3.1后报错“unknown type name __declspec”的解决方法
- Silverlight for Windows Phone Toolkit升级 新增四个控件
- 第七章、网络安全与主机基本防护: 限制端口, 网络升级与 SELinux
- java 程序升级之mysql Invalid column name 和 思考
- OAuth2 通用组件升级篇(开源,又见开源 - 新增支持淘宝登陆)
- 第7章 网络安全与主机基本防护:限制端口,网络升级与SELinux
- 在IIS6中新增可下载文件类型及IIS6中破除ASP上传200KB的限制
- OAuth2 通用组件升级篇(开源,又见开源 - 新增支持淘宝登陆)