【开发篇】二、属性绑定与校验

2023-09-22 14:35:14

请添加图片描述

1、@ConfigurationProperties自定义Bean属性绑定

前面读取yaml文件配置时,用过这个注解,先复习下它的用法。首先在yml配置文件中定义个属性:

# spring默认在用server,我加个s刻意回避下,别影响到服务启动
servers:
  hostAddr: http://127.0.0.1
  port: 9527
  timeout: 6000

定义实体类接收这个参数:

OData
@Component  //首先它得是受Spring管控的对象,即Bean,不然我哪怕拿到值,我怎么联系你给你
@ConfigurationProperties("servers")
public class ServerInfo {

	private String hostAddr:
	
	private int port:
	
	private long timeout;
}

接下来看下效果,懒得写UT,再获取IoC容器对象了 ,直接借用启动类run方法返回的IoC对象来获取上面这个Bean

@SpringBootApplication
public class MyApplication{

	public static void main(String[] args){
	
		ConfigurableApplicationContext applicationContext = SpringApplication.run(MyApplication.class,args);
		
		ServerInfo bean = applicationContext.getBean(ServerInfo.class);
		
		System.out.printin(bean);

	}
}

成功:
在这里插入图片描述

@ConfigurationProperties中写你要加载的属性的上一层级的,如果上一层还有父级,则xxx.xx就行。最后,@ConfigurationProperties注解使用时可能有warn信息:

在这里插入图片描述

要解除使用@ConfigurationProperties注释警告,引入以下这个依赖然后IDEA中点Hide隐藏就行:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

2、@EnableConfigurationProperties注解

有个关联知识点:@EnableConfigurationProperties注解,修改上面的代码,启动类上加@EnableConfigurationProperties注解:

@SpringBootApplication
@EnableConfigurationProperties(ServerInfo.class)
public class MyApplication{

	public static void main(String[] args){
	
		ConfigurableApplicationContext applicationContext = SpringApplication.run(MyApplication.class,args);
		
		ServerInfo bean = applicationContext.getBean(ServerInfo.class);
		
		System.out.printin(bean);

	}
}

此时,重启服务报错:excepted single matching bean but found 2

在这里插入图片描述

这里的原因是@EnableConfigurationProperties(ServerInfo.class)指定了ServerInfo.class,就会把这个类的Bean加载进来,而之前ServerInfo类中又用@Component注册了一次。解决报错把@Component注释掉就好。因此:

@EnableConfigurationProperties注解不能与@Component注解同时使用!

@ConfigurationProperties和@EnableConfigurationProperties,前者是做属性绑定的,后者是开启属性绑定,设定对应的目标是谁。

@EnableConfigurationProperties(ServerInfo.class)

后者的好处是可以通过这一行代码清晰看到都有哪些类从yml中读取了属性,使得对于这种类的管理不松散。

3、@ConfigurationProperties第三方Bean属性绑定

以上是给我们自定义的Bean注入属性,那第三方Bean呢?@ConfigurationProperties也可以实现。先写个测试的yml配置:

datasource:
  driverClassName: com.mysql.hhhh  # 我只是测拿数据,不连数据库,驱动随便写

再定义第三方Bean,@SpringBootApplication注解本身往下追就有@Configuration注解,所以这里直接在启动类里定义第三方Bean

@SpringBootApplication
public class MyApplication{

	@Bean
	@ConfigurationProperties(prefix = "datasource")
	public DruidDataSource dataSource(){
		DruidDataSource dataSource = new DruidDataSource();
		return dataSource;
	}

	public static void main(String[] args){
	
		ConfigurableApplicationContext applicationContext = SpringApplication.run(MyApplication.class,args);
		
		DruidDataSource bean = applicationContext.getBean(DruidDataSource.class);
		
		System.out.printin(bean);
		
		System.out.printin(bean.getDriverClassName());

	}
}

运行,属性绑定成功:

在这里插入图片描述

4、松散绑定

@ConfigurationProperties绑定属性支持属性名宽松绑定 ,即:

OData
@Component 
@ConfigurationProperties("servers")
public class ServerInfo {

	private String ipAddress:
	
	private int port:
	
	private long timeout;
}

属性的名字和配置文件的字段不用一模一样,以下配置都是生效的:

  • 驼峰
servers:
  ipAddress: 192.168.1.1
  port: 2345  
  timeout: -1

  • 下划线
servers:
  ip_address: 192.168.1.2
  port: 2345
  timeout: -1

  • 中划线(烤肉串写法,形似 00-0-0-0—,推荐写法)
servers:
  ip-address: 192.168.1.2
  port: 2345
  timeout: -1

  • 常量模式
servers:
  IP_ADDRESS: 192.168.1.2
  port: 2345
  timeout: -1

  • 随便加下划线或者中划线
servers:
  ip-ad-d_rEss: 192.168.1.2
  Port: 2345
  timeout: -1

当然实体类中的属性名也一样:

public class ServerInfo {

	private String ipADDRESS:
	
	private int port:
	
	private long timeout;
}

但@ConfigurationProperties注解的prefix属性,前缀名必须符合命名规范,即仅能使用纯小写字母、数字、下划线作为合法的字符,大写都不行。此外,@Value注解不支持宽松绑定,大小写不一样就会解析失败。

5、常用计量单位

SpringBoot支持JDK8提供的时间与空间计量单位,@DurationUnit和@DataSizeUnit注解标明所在属性的值的单位。还是上面的例子,加个属性serverTimeOut做调试:

servers:
  ipAddress: 192.168.1.1
  port: 2345  
  timeout: -1
  serverTimeOut: 6

此时, serverTimeOut值6的单位是不确定的,实体类中使用一个时间类Duration来接收:

OData
@Component 
@ConfigurationProperties("servers")
public class ServerInfo {

	private String ipAddress:
	
	private int port:
	
	private long timeout;

	private Duration serverTimeOut;
}

打印这个Bean,可以看到0.06s,即默认为ms:

在这里插入图片描述
接下来加注解指定这个属性的单位:


...
@DurationUnit(ChronoUnit.MINUTES)
private Duration serverTimeOut;
...

在这里插入图片描述

同理,还有空间单位,默认单位Byte,可加@DataSizeUnit注解指定:

OData
@Component 
@ConfigurationProperties("servers")
public class ServerInfo {

	private String ipAddress:
	
	private int port:
	
	private long timeout;

	@DurationUnit(ChronoUnit.MINUTES)
	private Duration serverTimeOut;

	@DataSizeUnit(DataUnit.MEGABYTES)
	private DataSize dataSize;
}

6、数据校验

开启数据校验有助于系统安全性,J2EE规范中JSR303规范定义了一组有关数据校验相关的API,先导入JSR303的依赖坐标:

<dependency>    
	<groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>

然后在需要校验的地方开启数据校验:

//springframework下的
@Valiated

然后给属性加具体的校验规则,相关注解有:

在这里插入图片描述

此时,运行出现报错:

在这里插入图片描述

报错信息为找不到具体的实现,这就和JDBC和mysql驱动是一个意思,有接口,代码能写,但一运行,没有实现,跑不起来。再引入JSR303校验框架的实现,如Hibernate:

<dependency>    
	<groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>

再运行,校验成功:

在这里插入图片描述

JSR303的校验,用处很多,比如写接口时,对前端的传参做校验,只需要在Dto类中的属性加相关注解即可,如:

在这里插入图片描述

添加校验规则:

在这里插入图片描述

7、yaml绑定值的坑–关于进制

在yaml中定义一个属性password,取值0127,使用属性绑定或者@Value取值,打印这个值:

在这里插入图片描述
在这里插入图片描述
问题的原因就是,在yaml中,书写数字和简单字符串都不用加引号,而0127又特殊在以0开头,后面的字符在0-7之间,被当作了八进制,可通过加引号解决:

datasource:
  password: "0127"

在这里插入图片描述
即:注意yaml文件中对于数字的定义支持进制书写格式,如需使用字符串请使用引号明确标注

更多推荐

企业电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

功能描述1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所有的立项信息。主要功能包含:招标立项申请、非招标立项申请、采购立项管理。3、采购项目管理:可对项目采购过程全流程管

OpenCV(四十七):RANSAC优化特征点匹配

1.RANSAC算法介绍RANSAC是一种常用的参数估计方法,全称为RandomSampleConsensus(随机抽样一致性)。它的主要思想是通过随机选择一部分数据样本,构建模型并评估其拟合程度,迭代过程中逐步优化模型,最终得到一个拟合较好的模型。其基本流程如下:随机取样,计算规律(特征点匹配中计算单应矩阵)测试规律

【JMeter】threadNum:将接口查询结果列表按顺序赋值给各线程

【软件测试行业现状】2023年了你还敢学软件测试?未来已寄..测试人该何去何从?【自动化测试、测试开发、性能测试】使用JMeter做性能测试会遇到这么一个场景:后面的请求需要根据前面的查询列表结果通过正则表达式提取器取值后赋值,而后面用户的赋值必须是唯一的,此时该如何做?如果按编程思维来说,这个问题并不难。只需要把前面

打卡中国人民大学与加拿大女王大学金融硕士项目,读研梦想从这里起飞

2024年硕士研究生网报即将于10月8日开启,中国人民大学硕士研究生招生简章也已公布,计划报考人大研究生的在职人士你们复习的怎么样了呢,录取的比率逐年下降,想要成功上岸还是需要做多重准备的,除了PlanA我们还要做PlanB或PlanC等,中国人民大学与加拿大女王大学金融硕士项目邀你来打卡,你的读研梦想也可以从这里起飞

Hadoop的YARN高可用

一、YARN简介Hadoop2.0即第二代Hadoop,由分布式存储系统HDFS、并行计算框架MapReduce和分布式资源管理系统YARN三个系统组成,其中YARN是一个资源管理系统,负责集群资源管理和调度,MapReduce则是运行在YARN上的离线处理框架。YARN一种开源的分布式资源管理和作业调度技术,它是作为

通过java代码在指定目录生成一个指定内容的vue文件

可能很多人觉得用java写vue会更快或者有什么固定格式但其实那需要构建一套非常完整的系统架构如果什么都没构建那么用前端编辑器肯定是比你用java写的快而且写的好的我们直接创建一个类叫Main编写代码如下importjava.io.FileWriter;importjava.io.IOException;publicc

如何搭建数据驱动自动化测试框架?

前言说到数据驱动自动化测试,你会不会有这样的疑问:数据怎么管理?数据怎么才能驱动测试用例执行?到底怎么样才算数据驱动?那么本篇文章就教你如何进行数据驱动测试,相信你一定能对数据驱动自动化测试有一个不一样的理解,希望这篇文章能帮助还在懵懵懂懂的你了解数据驱动测试,如何来做数据驱动测试?那么就跟上我的脚步吧^_^项目介绍1

动态近场通信标签:如何使用C++与微控制器进行NFC交互的完整指南

1.引言近场通信(NFC)技术已经成为现代电子设备中不可或缺的一部分。从手机支付到门禁系统,NFC为我们的日常生活带来了许多便利。但是,你知道我们可以如何使用C++与微控制器进行NFC交互吗?在本文中,我们将深入探讨如何使用开源NFC标签与微控制器进行通信。2.NFC简介近场通信(NFC)是一种建立在射频识别(RFID

2023 ICPC 网络赛 第一场 部分题解 (待完善)

DTransitivity题解:根据题意可以推出结论:如果存在连通块,那么这个连通块要满足条件,必然是满连通块.一共有两种情况1.存在一个连通块不是满连通块设cnt表示连通块的节点个数,num表示连通块边的个数一个连通块的贡献=cnt*(cnt-1)/2-num;那么最终答案=连通块贡献之和2.所有连通块都是满连通块因

2023!6招玩转 Appium 自动化测试

Appium是个什么鬼Appium是一个移动端的自动化框架,可用于测试原生应用,移动网页应用和混合型应用,且是跨平台的。可用于IOS和Android以及firefox的操作系统。原生的应用是指用android或ios的sdk编写的应用,移动网页应用是指网页应用,类似于ios中safari应用或者Chrome应用或者类浏

【react】使用useEffect操作dom

简言在学习react时,需要了一个需要在useEffect里操作dom的用法。一般不推荐这么干,如果是函数组件在一渲染已挂载后立即需要操作dom绑定事件等可以参考下面解决方法。描述官网交错运动示例这个示例中,usePointerPosition()Hook追踪当前指针位置。尝试移动光标或你的手指到预览区域上方,可以看到

热文推荐