数据校验:Spring Validation

Spring Validation概述

在开发中,我们经常遇到参数校验的需求,比如用户注册的时候,要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式,我们会把校验的代码和真正的业务处理逻辑耦合在起,而且如果未来要新增一种校验逻辑也需要在修改多个地方。而spring validation允许通过注解的方式来定义对象校验规则,把校验和业务逻辑分离开,让代码编写更加方便。Spring Validation其实就是对Hibernate Validator进一步的封装,方便在Spring中使用。

在Spring中有多种校验的方式
第一种是通过实现org.springframework.validation.Validator接口,然后在代码中调用这个类

第二种是按照Bean Validation方式来进行校验,即通过注解的方式

第三种是基于方法实现校验

第四种实现自定义校验

 通过实现Validator接口实现

创建子模块 spring6-validator

引入依赖

    <dependencies><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>7.0.5.Final</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>jakarta.el</artifactId><version>4.0.1</version></dependency></dependencies>

创建实体类,定义属性,创建对应的set与get方法

public class Person {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

创建类,实现接口,实现接口的方法,编写校验逻辑

supports方法用来表示此校验用在哪个类型上
validate是设置校验逻辑的地点,其中ValidatorUtils,是Spring封装的校验工具类,帮助快速实现校验

public class PersonValidator implements Validator {@Overridepublic boolean supports(Class<?> clazz) {//supports方法用来表示此校验用在哪个类型上return Person.class.equals(clazz);}//校验规则@Overridepublic void validate(Object target, Errors errors) {//validate是设置校验逻辑的地点,其中ValidatorUtils,是Spring封装的校验工具类,帮助快速实现校验//name不能为空ValidationUtils.rejectIfEmpty(errors,"name","name.empty","name is null");//age 不能小于0 不能大于100Person p = (Person) target;if (p.getAge() < 0){errors.rejectValue("age","age.value.error","age < 0");} else if (p.getAge() > 200) {errors.rejectValue("age","age.value.old","age > 200");}}
}

完成测试

//校验测试
public class TestPerson {public static void main(String[] args) {//创建person对象Person person = new Person();//创建person对应databinderDataBinder binder = new DataBinder(person);//设置 校验器binder.setValidator(new PersonValidator());//调用方法执行校验binder.validate();//输出校验结果BindingResult result = binder.getBindingResult();System.out.println(result.getAllErrors());}
}

Bean Validation注解实现


使用Bean Validation校验方式,就是如何将Bean Validation需要使用的javax.validation.ValidatorFactoryjavax.validation.Validator注入到容器中。

spring默认有一个实现类LocalValidatorFactoryBean,它实现了上面Bean Validation中的接口,并且也实现了org.springframework.validation.Validator接口。


创建配置类ValidationConfig,配置LocalValidatorFactoryBean

@Configuration
@ComponentScan("com.yogurt.spring6.validator.two")
public class ValidationConfig {@Beanpublic LocalValidatorFactoryBean validator(){return new LocalValidatorFactoryBean();}
}

创建实体类,定义属性,创建对应的set与get方法,在属性上面使用注解设置校验规则

常用注解说明


@NotNull 限制必须不为null
@NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0

@NotBlank 只作用于字符串类型,字符串不为空,并且trim0后不为空串@DecimalMax(value) 限制必须为一个不大于指定值的数字

@DecimalMin(value) 限制必须为一个不小于指定值的数字

@Max(value) 限制必须为一个不大于指定值的数字

@Min(value)限制必须为一个不小于指定值的数字限制必须符合指定的正则表达式@Pattern(value)

@size(max,min) 限制字符长度必须在min到max之间

@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

public class User {@NotNullprivate String name;@Min(0)@Max(150)private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

 在属性上面使用注解设置校验规则

创建校验器

用原生:import jakarta.validation.Validator; 

@Service
public class MyValidation1 {@Autowiredprivate Validator validator;private boolean validatorByUserOne(User user){Set<ConstraintViolation<User>> validate = validator.validate(user);return validate.isEmpty();}
}

用spring框架中:import org.springframework.validation.Validator;

@Service
public class MyValidation2 {@Autowiredprivate Validator validator;public boolean validatorByUserTwo(User user){BindException bindException = new BindException(user, user.getName());validator.validate(user,bindException);return bindException.hasErrors();}
}

完成测试

原生测试:

    @Testpublic void testValidationOne(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation1 validation1 = context.getBean(MyValidation1.class);User user = new User();//user.setName("luck");//user.setAge(20);boolean message = validation1.validatorByUserOne(user);System.out.println(message);}

正常结果 

spring框架测试:

    @Testpublic void testValidationTwo(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation2 validation2 = context.getBean(MyValidation2.class);User user = new User();
//        user.setName("luck");
//        user.setAge(20);boolean message = validation2.validatorByUserTwo(user);System.out.println(message);}
}

报错:
java.lang.IllegalArgumentException: Object name must not be null

修改-->设置姓名和年龄:

    @Testpublic void testValidationTwo(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation2 validation2 = context.getBean(MyValidation2.class);User user = new User();user.setName("luck");user.setAge(20);boolean message = validation2.validatorByUserTwo(user);System.out.println(message);}
}

基于方法实现校验 

 创建配置类ValidationConfig

@Configuration
@ComponentScan("com.yogurt.spring6.validator.three")
public class ValidationConfig {@Beanpublic MethodValidationPostProcessor validationPostProcessor(){return new MethodValidationPostProcessor();}
}

创建实体类,定义属性,创建对应的set与get方法,在属性上面使用注解设置校验规则

public class User {@NotNullprivate String name;@Min(0)@Max(150)private int age;@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")@NotBlank(message = "手机号码不能为空")private String phone;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}
}

 在属性上面使用注解设置校验规则

创建校验器

@Service
@Validated
public class MyService {public String testMethod(@NotNull @Valid User user){return user.toString();}
}

 

完成测试

public class TestUser {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService service = context.getBean(MyService.class);User user = new User();//user.setName("lucy");//user.setPhone("15545451223");service.testMethod(user);}
}

报错:Exception in thread "main" jakarta.validation.ConstraintViolationException: testMethod.arg0.name: 不能为null, testMethod.arg0.phone: 手机号码不能为空

修改-->设置姓名和手机号:

public class TestUser {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService service = context.getBean(MyService.class);User user = new User();user.setName("lucy");user.setPhone("15545451223");service.testMethod(user);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/141737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

K8S篇之etcd数据备份与恢复

一、etcd备份与恢复 基本了解&#xff1a; 1、k8s 使用etcd数据库实时存储集群中的数据&#xff0c;安全起见&#xff0c;一定要备份。 2、备份只需要在一个节点上备份就可以了&#xff0c;每个节点上的数据是同步的&#xff1b;但是数据恢复是需要在每个节点上进行。 3、etcd…

系统韧性研究(4)| 系统韧性的技术分类

系统韧性技术是任何提高系统韧性的架构、设计或实现技术。这些技术&#xff08;例如缓解措施&#xff0c;如冗余、保障措施和网络安全对策&#xff09;或被动地抵御逆境或主动检测逆境&#xff0c;并对其做出反应&#xff0c;亦或者从它们造成的伤害中恢复过来。系统韧性技术是…

软件测试/测试开发丨探索标识符在编程中的重要性

点此获取更多相关资料 什么是标识符 在 Python 中&#xff0c;标识符是用来标识变量、函数、类、模块和其他对象的名称。需要注意的是&#xff0c;在定义标识符的时候&#xff0c;虽然很自由&#xff0c;但是也不能随心所欲&#xff0c;合法的标识符需要遵从一定的规范。 命…

ArcGIS实现矢量区域内所有要素的统计计算

1、任务需求&#xff1a;统计全球各国所有一级行政区相关属性的总和。 &#xff08;1&#xff09;有一个全球一级行政区的矢量图&#xff0c;包含以下属性&#xff08;洪灾相关属性 province.shp&#xff09; &#xff08;2&#xff09;需要按照国家来统计各个国家各属性的总值…

突然消失的桌面文件如何恢复?详细教程让你轻松解决问题!

桌面文件突然消失&#xff0c;对于很多人来说&#xff0c;可能是个令人头疼的问题。这些文件可能包含重要的信息&#xff0c;也可能是数日甚至数周的努力成果。那么&#xff0c;当这种情况发生时&#xff0c;我们如何恢复丢失的文件呢&#xff1f;本文将提供一些实用的建议。 1…

【ArcGIS Pro微课1000例】0031:las点云提取(根据范围裁剪点云)

本文讲解ArcGIS Pro3.0中,las点云数据的提取(根据范围裁剪点云)方法。 文章目录 一、加载数据二、工具介绍三、点云裁剪一、加载数据 打开ArcGIS Pro,新建地图,加载配套实验数据包中的0031.rar中的点云数据point.las与范围bound.shp,如下图所示: 二、工具介绍 名称:提…

table表格的某一行数据如何回填

目的&#xff1a;table表格的某一行数据的输入框按钮触发对话框&#xff0c;对话框选择的数据再回填到table表格的这一行中。 1.插槽中传递本行的index: v-slot"{ row, $index }" 2.点击事件或者change事件传递index: click"val > tpmClicked($index)"…

一张图搞懂什么是BCD8421编码

如图所示 BCD8421编码的意义是 用四位二进制数表达一位的十进制数 因此十进制下的0&#xff5e;9在BCD8421编码下与其二进制表达是一样的 而多位的十进制数 比如说“10” 则需要将它拆分成两个单独的数“1”和“0” 分别用BCD8421编码表示这两个数 十进制“1” -> 0001 十进…

JAVA基础7:数组

1.数组定义格式 1&#xff09;数组概述 一次性声明大量的用于存储数据的变量 要存储的数据通常都是同类型数据&#xff0c;比如&#xff1a;考试成绩 数组&#xff08;array)是一种用于存储多个相同类型数据的存储模型 2&#xff09;数组定义格式 格式一&#xff1a;数据类…

在虚拟环境中pip包不在虚拟环境里

这里写自定义目录标题 结合网上多个大佬的方法终于解决了. 首先修改自己虚拟环境目录下的site文件: vim /home/XXX/.conda/envs/XXX/lib/pythonXXX/site.py 把 USER_BASE 和 USER_SITE 改成虚拟环境目录. USER_BASE: ‘/home/XXX/.conda/envs/XXX’ (exists) USER_SITE: ‘/ho…

内衣洗衣机和手洗哪个干净?好用的内衣洗衣机推荐

在日常生活中&#xff0c;我们的衣服不可避免地会沾染上各种细菌、毛发和污渍&#xff0c;将它们与贴身衣物混合清洗&#xff0c;很容易发生交叉感染&#xff0c;而被感染后&#xff0c;贴身衣物也有可能导致我们人体引起皮肤病。这也是为什么大部分人都喜欢用手洗的原因&#…

c# 和 c++ 匿名互相传递参数

在C#和C之间进行匿名参数传递需要使用Interop服务。下面是一个示例&#xff0c;展示了如何在C#和C之间传递匿名参数&#xff1a; 在C#中&#xff1a; using System; using System.Runtime.InteropServices;// 定义C中的匿名函数签名 [UnmanagedFunctionPointer(CallingConven…

@CacheInvalidate(name = “xxx“, key = “#results.![a+b]“,multi = true)是什么意思

@CacheInvalidate 注解是 JetCache 框架提供的注解,它是由阿里巴巴开源的组织 Alibaba Group 开发和维护的。JetCache 是一款基于注解的缓存框架,提供了丰富的缓存功能和灵活的配置选项,可用于增强应用程序的性能和可扩展性。JetCache 支持多种缓存后端,包括内存缓存、Redi…

矩阵的除法

B/A 如果矩阵A可逆&#xff0c;那么 证明&#xff1a; A/AB 如果矩阵A和B都可逆&#xff0c;那么 证明&#xff1a;

基于回溯搜索算法优化概率神经网络PNN的分类预测 - 附代码

基于回溯搜索算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于回溯搜索算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于回溯搜索优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

优雅的Java编程:将接口对象作为方法参数

theme: smartblue 目录 概述 在Java编程中&#xff0c;方法的参数传递方式通常是通过基本类型、对象引用或者集合等方式。然而&#xff0c;一种更加优雅且灵活的设计模式是将接口对象作为方法的参数。这种方式为我们带来了许多好处&#xff0c;包括降低耦合性、实现多态性和可…

Jenkins 构建CICD

GitLab GitLab安装 https://gitlab.cn/install/?versionce CentOS 下安装 1. 安装和配置必须的依赖项 在 CentOS 7上&#xff0c;下面的命令也会在系统防火墙中打开 HTTP、HTTPS 和 SSH 访问。这是一个可选步骤&#xff0c;如果您打算仅从本地网络访问极狐GitLab&#xf…

Java集合(全)

Java提供了多种集合框架类&#xff0c;每种都有不同的特性和用途。以下是Java中常见的集合类&#xff1a; 1、List&#xff08;列表&#xff09;: ArrayList ArrayList 是 Java 集合框架中的一个常用类&#xff0c;实现了动态数组的数据结构。与传统的数组相比&#xff0c;A…

【现场问题】datax中write部分为Oracle的时候插入clolb类型字段,插入的数据为string且长度过场问题

datax的Oraclewriter 报错显示查询报错展示查找datax中的数据插入模块 报错显示 occurred during batching: ORA-01704: string literal too long 查询报错展示 基本上查到的都是这样的&#xff0c;所以锁定是clob的字段类型的问题&#xff0c;而且是只有Oracle出问题&#…

觉非科技发布【轻地图高速NOA智驾方案】|地平线,觉非科技,MobileDrive超捷生态协作实现技术落地

11月10日&#xff0c;2023世界新汽车技术合作生态展期间&#xff0c;觉非科技正式发布了基于地平线征程系列以及MobileDrive超捷规控系统的【轻地图高速NOA智驾解决方案】。该方案首次实现了从芯片能力输出、到数据闭环建设、再到规控部署的产业生态链协作与打通&#xff0c;为…