1.宽松绑定/松散绑定
说明:
在进行属性绑定时,可能会遇到如下情况,为了进行标准命名,开发者会将属性名严格按照驼峰命名法书写,在yml配置文件中将datasource修改为dataSource,如下:
dataSource: driverClassName: com.mysql.jdbc.Driver
此时程序可以正常运行,然后又将代码中的前缀datasource修改为dataSource,如下:
@Bean @ConfigurationProperties(prefix = "dataSource") public DruidDataSource datasource(){ DruidDataSource ds = new DruidDataSource(); return ds; }
此时就发生了编译错误,而且并不是idea工具导致的,运行后依然会出现问题,配置属性名dataSource是无效的
Configuration property name 'dataSource' is not valid: Invalid characters: 'S' Bean: datasource Reason: Canonical names should be kebab-case ('-' separated), lowercase alpha-numeric characters and must start with a letter Action: Modify 'dataSource' so that it conforms to the canonical names requirements.
为什么会出现这种问题,这就要来说一说springboot进行属性绑定时的一个重要知识点了,有关属性名称的宽松绑定,也可以称为宽松绑定。
宽松绑定:
实际上是springboot进行编程时人性化设计的一种体现,即配置文件中的命名格式与变量名的命名格式可以进行格式上的最大化兼容。
兼容到什么程度呢?几乎主流的命名格式都支持,例如:
在ServerConfig中的ipAddress属性名
@Component @Data @ConfigurationProperties(prefix = "servers") public class ServerConfig { private String ipAddress; }
可以与下面的配置属性名规则全兼容
servers: ipAddress: 192.168.0.2 # 驼峰模式 ip_address: 192.168.0.2 # 下划线模式 ip-address: 192.168.0.2 # 烤肉串模式 IP_ADDRESS: 192.168.0.2 # 常量模式
以上4种模式最终都可以匹配到ipAddress这个属性名。在进行匹配时,配置中的名称要去掉中划线和下划线后,忽略大小写的情况下去与java代码中的属性名进行忽略大小写的等值匹配,以上4种命名去掉下划线中划线忽略大小写后都是一个词ipaddress,java代码中的属性名忽略大小写后也是ipaddress,这样就可以进行等值匹配了。不过springboot官方推荐使用烤肉串模式,也就是中划线模式。
到这里我们掌握了一个知识点,就是命名的规范问题。再来看开始出现的编程错误信息
Configuration property name 'dataSource' is not valid: Invalid characters: 'S' Bean: datasource Reason: Canonical names should be kebab-case ('-' separated), lowercase alpha-numeric characters and must start with a letter Action: Modify 'dataSource' so that it conforms to the canonical names requirements.
其中Reason描述了报错的原因,规范的名称应该是烤肉串(kebab)模式(case),即使用-分隔,使用小写字母数字作为标准字符,且必须以字母开头。然后再看我们写的名称dataSource,就不满足上述要求,在书写前缀时,这个词不是随意支持的,必须使用上述标准。
注:
以上规则仅针对springboot中@ConfigurationProperties注解进行属性绑定时有效,对@Value注解进行属性映射无效。
2.常用计量单位绑定
在前面的配置中,我们书写了如下配置值,其中第三项超时时间timeout描述了服务器操作超时时间,当前值是-1表示永不超时。
servers: ip-address: 192.168.0.1 port: 2345 timeout: -1
但是每个人都这个值的理解会产生不同,可以是分钟,可以是小时,可以是秒。
除了加强约定之外,springboot充分利用了JDK8中提供的全新的用来表示计量单位的新数据类型,从根本上解决这个问题。以下模型类中添加了两个JDK8中新增的类,分别是Duration和DataSize
@Component @Data @ConfigurationProperties(prefix = "servers") public class ServerConfig { @DurationUnit(ChronoUnit.HOURS) private Duration serverTimeOut; @DataSizeUnit(DataUnit.MEGABYTES) private DataSize dataSize; }
Duration:表示时间间隔,可以通过@DurationUnit注解描述时间单位,例如上例中描述的单位为小时(ChronoUnit.HOURS)
DataSize:表示存储空间,可以通过@DataSizeUnit注解描述存储空间单位,例如上例中描述的单位为MB(DataUnit.MEGABYTES)
使用上述两个单位就可以有效避免因沟通不同步或文档不健全导致的信息不对称问题,从根本上解决了问题,避免产生误读。
Druation常用单位如下:
DataSize常用单位如下: