最近公司项目在做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.x升级踩坑--新增Configuration property name限制的更多相关文章

  1. jQuery升级踩坑大全

    jQuery升级踩坑大全 背景 jQuery想必各个web工程师都再熟悉不过了,不过现如今很多网站还采用了很古老的jQuery版本.其实如果早期版本使用不当,可能会有DOMXSS漏洞,非常建议升级到j ...

  2. jQuery升级踩坑之路

    1.使用了被废弃的jQuery.browser属性 jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support . 在更 ...

  3. async语法升级踩坑小记

    从今年过完年回来,三月份开始,就一直在做重构相关的事情. 就在今天刚刚上线了最新一次的重构代码,希望高峰期安好,接近半年的Node.js代码重构. 包含从callback+async.waterfal ...

  4. spring-cloud /pause 平滑升级 踩坑记录

    0.客户端添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...

  5. jQuery版本升级踩坑大全

    背景 -------------------------------------------------------------------------------- jQuery想必各个web工程师 ...

  6. SpringBoot1.x升级SpringBoot2.x踩坑之文件上传大小限制

    SpringBoot1.x升级SpringBoot2.x踩坑之文件上传大小限制 前言 LZ最近升级SpringBoo框架到2.1.6,踩了一些坑,这里介绍的是文件上传大小限制. 升级前 #文件上传配置 ...

  7. Spark 1.6升级2.x防踩坑指南

    原创文章,谢绝转载 Spark 2.x自2.0.0发布到目前的2.2.0已经有一年多的时间了,2.x宣称有诸多的性能改进,相信不少使用Spark的同学还停留在1.6.x或者更低的版本上,没有升级到2. ...

  8. .NET Core 从1.1升级到2.0记录(Cookie中间件踩坑)

    .NET Core 2.0 新时代 万众瞩目的.NET Core 2.0终于发布了,原定于9.19的dotnetconf大会的发布时间大大提前了1个月,.NET Core 2.0/.NET Stand ...

  9. Rxjava1升级Rxjava2踩坑一记

    Rxjava1升级Rxjava2坑 共存问题 通常情况下,如果我们希望在一个模块中既想使用rxjava1又想使用rxjava2,这个时候在运行的时候会出现一下报错: ... APK META/-INF ...

随机推荐

  1. redis持久化的两种方式RDB和AOF

    原文链接:http://www.cnblogs.com/tdws/p/5754706.html Redis的持久化过程中并不需要我们开发人员过多的参与,我们要做的是什么呢?除了深入了解RDB和AOF的 ...

  2. [淘宝客技术篇005]如何取站点id和推广位id

    我们知道,生成一个用于推广的淘客链接,是需要指定对应的站点id和推广位id的,也就是siteid和adzoneid. 今天,火星来客跟大家分享两个不同的方法获取站点id和推广位id. 方法一:直接获取 ...

  3. 简单说一下你对http和https的理解

    http是一种超文本传输协议,传输的数据都是未加密的,也就是显示在明面上的,是现在互联网上应用最为广泛的一种网络协议,相对来说不太安全,但是所需成本很小.http一般的端口号为80. https则是具 ...

  4. .Net基础篇_学习笔记_第六天_类型转换和方法(函数)简介

    类型转换:Convert.ToInt32();  int.Parse();  int.TryParse(); Convert.ToInt32(); 的本质就是在使用 int.Parse(); int. ...

  5. s-s-r + 锐-速

    环境:centos 7 1. wget --no-check-certificate https://freed.ga/github/shadowsocksR.sh; bash shadowsocks ...

  6. Ubuntu18.04安装测试TensorFlow-GPU

    1 安装Ubuntu18.04.03 lts spt@spt-ts:~$ lsb_release -a No LSB modules are available. Distributor ID: Ub ...

  7. Cookie的临时存储和定时存储

    Cookie解决了不同请求的数据共享问题.是由服务器保存在客户端的小文本文件,包含了用户的信息,可以避免用户重复输入用户名和密码进行登录.浏览器请求Cookie,服务器响应时返回Cookie,浏览器存 ...

  8. 第1次作业-Numpy练习

    1.创建一个边界值为1而内部都是0的数组,图例如下:[提示:]解此题可以先把所有值都设置为1,这是大正方形:其次,把边界除外小正方形全部设置为0.本题用到numpy的切片原理.多维数组同样遵循x[st ...

  9. 三段式有限状态机Verilog代码

    状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作.完成特定操作的控制中心.有限状态机简写为FSM(Finite State Machine),主 ...

  10. 从零开始使用 Webpack 搭建 Vue 开发环境

    创建项目 先创建一个空目录,在该目录打开命令行,执行 npm init 命令创建一个项目(无法执行 npm 命令?需要先安装 Node),这个过程会提示输入一些内容,随意输入就行,完成后会自动生成一个 ...