spring数据校验:Validation

news/2024/10/22 17:20:15/

目录

Spring Validation概述

通过Validator接口实现

Bean 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>

第三步 创建实体类,定义属性和方法

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;}
}

 第四步 创建类实现Validator接口,实现接口方法指定校验规则

public class PersonValidator implements Validator {@Overridepublic boolean supports(Class<?> clazz) {return Person.class.equals(clazz);}@Overridepublic void validate(Object object, Errors errors) {ValidationUtils.rejectIfEmpty(errors, "name", "name.empty");Person p = (Person) object;if (p.getAge() < 0) {errors.rejectValue("age", "error value < 0");} else if (p.getAge() > 110) {errors.rejectValue("age", "error value too old");}}
}

上面定义的类,其实就是实现接口中对应的方法,supports方法用来表示此校验用在哪个类型上,validate是设置校验逻辑的地点,其中ValidationUtils,是Spring封装的校验工具类,帮助快速实现校验。

第五步 使用上述Validator进行测试

public class TestMethod1 {public static void main(String[] args) {//创建person对象Person person = new Person();person.setName("lucy");person.setAge(-1);// 创建Person对应的DataBinderDataBinder binder = new DataBinder(person);// 设置校验binder.setValidator(new PersonValidator());// 由于Person对象中的属性为空,所以校验不通过binder.validate();//输出结果BindingResult results = binder.getBindingResult();System.out.println(results.getAllErrors());}
}

Bean Validation注解实现 

使用Bean Validation校验方式,就是如何将Bean Validation需要使用的javax.validation.ValidatorFactory 和javax.validation.Validator注入到容器中。spring默认有一个实现类LocalValidatorFactoryBean,它实现了上面Bean Validation中的接口,并且也实现了org.springframework.validation.Validator接口。

第一步 创建配置类,配置LocalValidatorFactoryBean

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

第二步 创建实体类,使用注解定义校验规则

public class User {@NotNullprivate String name;@Min(0)@Max(120)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;}
}

常用注解说明

  • @NotNull 限制必须不为null
  • @NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0
  • @NotBlank 只作用于字符串类型,字符串不为空,并且trim()后不为空串
  • @DecimalMax(value) 限制必须为一个不大于指定值的数字
  • @DecimalMin(value) 限制必须为一个不小于指定值的数字
  • @Max(value) 限制必须为一个不大于指定值的数字
  • @Min(value) 限制必须为一个不小于指定值的数字
  • @Pattern(value) 限制必须符合指定的正则表达式
  • @Size(max,min) 限制字符长度必须在min到max之间
  • @Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式  

第三步 使用两种不同的校验器实现

(1)使用jakarta.validation.Validator校验

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

(2)使用org.springframework.validation.Validator校验

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

第四步 测试

public class TestMethod2 {@Testpublic void testMyService1() {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService1 myService = context.getBean(MyService1.class);User user = new User();user.setAge(-1);boolean validator = myService.validator(user);System.out.println(validator);}@Testpublic void testMyService2() {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService2 myService = context.getBean(MyService2.class);User user = new User();user.setName("lucy");user.setAge(130);user.setAge(-1);boolean validator = myService.validaPersonByValidator(user);System.out.println(validator);}
}

基于方法实现校验

第一步 创建配置类,配置MethodValidationPostProcessor

@Configuration
@ComponentScan("com.atguigu.spring6.validation.method3")
public class ValidationConfig {@Beanpublic MethodValidationPostProcessor validationPostProcessor() {return new MethodValidationPostProcessor();}

第二步 创建实体类,使用注解设置校验规则

public class User {@NotNullprivate String name;@Min(0)@Max(120)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类,通过注解操作对象

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

第四步 测试

public class TestMethod3 {@Testpublic void testMyService1() {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService myService = context.getBean(MyService.class);User user = new User();user.setAge(-1);myService.testParams(user);}
}

实现自定义校验

第一步 自定义校验注解

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {CannotBlankValidator.class})
public @interface CannotBlank {//默认错误消息String message() default "不能包含空格";//分组Class<?>[] groups() default {};//负载Class<? extends Payload>[] payload() default {};//指定多个时使用@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})@Retention(RetentionPolicy.RUNTIME)@Documented@interface List {CannotBlank[] value();}
}

第二步 编写真正的校验类

public class CannotBlankValidator implements ConstraintValidator<CannotBlank, String> {@Overridepublic void initialize(CannotBlank constraintAnnotation) {}@Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {//null时不进行校验if (value != null && value.contains(" ")) {//获取默认提示信息String defaultConstraintMessageTemplate = context.getDefaultConstraintMessageTemplate();System.out.println("default message :" + defaultConstraintMessageTemplate);//禁用默认提示信息context.disableDefaultConstraintViolation();//设置提示语context.buildConstraintViolationWithTemplate("can not contains blank").addConstraintViolation();return false;}return true;}
}


http://www.ppmy.cn/news/77018.html

相关文章

Spring探索——既生@Resource,何生@Autowired?

提到Spring依赖注入&#xff0c;大家最先想到应该是Resource和Autowired&#xff0c;很多文章只是讲解了功能上的区别&#xff0c;对于Spring为什么要支持两个这么类似的注解却未提到&#xff0c;属于知其然而不知其所以然。不知大家在使用这两个注解的时候有没有想过&#xff…

欧奈尔杯柄形态选股公式,突破杯柄高点发出信号

杯柄形态是由美国著名的成长股投资大师威廉欧奈尔提出的&#xff0c;在其经典著作《笑傲股市》中有详细介绍。 根据欧奈尔在书中的描述&#xff1a; 从侧面观察其轮廓时&#xff0c;最重要的价格形态之一看起来就像是一个带柄的茶杯。杯状形态可以持续7~56周不等&#xff0c;但…

SSH远程连接时报错kex_exchange_identification: Connection closed by remote host

简介 在SSH服务器上进行远程内容时&#xff0c;会经常出现kex_exchange_identification: Connection closed by remote host内容&#xff0c;主要是由于远程计算机登录节点的数量限制问题。 解释 在 SSH 服务器上&#xff0c;最大并发登录会话数是由 ‘MaxSessions’ 参数来…

PostgreSQL 源码部署

文章目录 说明1. 准备工作1.1 源码包下载1.2 解压安装目录1.3 安装依赖包1.4 添加用户1.5 创建数据目录 2. 编译安装2.1 源码编译2.2 配置环境变量2.3 初始化数据库2.4 启动数据库2.5 连接数据库 3. 参数调整3.1 配置 pg_hba3.2 监听相关2.4 日志文件2.5 内存参数 说明 本篇文…

第三讲 Ubuntu系统FFmpeg环境搭建

Ubuntu系统安装 0-对于Ubuntu系统&#xff0c;系统默认是已经安装FFmpeg的&#xff0c;可通过ffmpeg -version,查看系统的已经安装的版本信息。如果系统内没有安装则需要按照一下步骤进行。 1-获取编译环境依赖&#xff1a; sudo apt-get update -qq && sudo apt-ge…

如何在 Linux 服务器上更改分区方案?

在 Linux 服务器上&#xff0c;分区方案对于数据存储和系统管理至关重要。当服务器的存储需求发生变化或者需要重新组织分区时&#xff0c;更改分区方案是一个常见的任务。 本文将详细介绍如何在 Linux 服务器上更改分区方案。 步骤一&#xff1a;备份数据 在更改分区方案之前…

C++的历史

C是一种广泛使用的编程语言。C于1983年由丹尼斯里奇&#xff08;Dennis Ritchie&#xff09;在贝尔实验室创造&#xff0c;它是C语言的扩展。C的设计初衷是为了提高代码的可重用性和可维护性。它允许开发人员使用面向对象编程&#xff08;OOP&#xff09;范例&#xff0c;这使得…

BFT 最前线 | 王小川:2033机器智慧将超人类;扎克伯格财富暴涨;哈工大:能跳跃的昆虫机器人;北京支持“1+4”机器人领域

原创 | 文 BFT机器人 名人动态 CELEBRITY NEWS 01 王小川&#xff1a;10年后机器智慧将超过人类 年底将推出对标GPT-3.5的模型 科技预言大师雷库兹韦尔说人工智能的奇点&#xff0c;机器智慧超过人类会发生在2045年&#xff0c;王小川的判断比这更激进&#xff0c;他认为这一…