第十章、数据校验:Validation
1、SpringValidation概念
1、就是在开发的时候,我们会遇到登录或者注册的校验
2、例如:要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式
3、如果用普通方法,我们会把校验的代码和真正的业务逻辑耦合在一起
4、如果未来新增加方法,就会要改很多地方
5、而spring validation允许通过注解的方式来定义对象校验规则,把校验和业务逻辑分离开,让代码编写更加方便
6、Spring Validation其实就是对Hibernate Validator进一步的封装,方便在Spring中使用。
2、有多种校验的方法
1、第一种是通过实现org.springframework.validation.Validator接口,然后在代码中调用这个类
1、基本步骤

2、注意:
supports方法用来表示此校验用在哪个类型上,
validate是设置校验逻辑的地点,其中ValidationUtils,是Spring封装的校验工具类,帮助快速实现校验。
1、创建一个子模块Spring6-validator
1、注入相关依赖
<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>
2、创建一个实体类及set方法
1、创建一个Person.java
package com.atguigu.spring6.validation.method1;
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;
}
}
3、创建一个实现Validator接口
1、创建类实现Validator接口,实现接口方法指定校验规则
package com.atqt.spring6.vaalidator.one;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
public class PersonValidator implements Validator {
// 此方法是用来校验用在哪个类型上
@Override
public boolean supports(Class<?> clazz) {
return Person.class.equals(clazz);
}
// 是设置校验逻辑的地点
// 设置校验的规则
@Override
public void validate(Object target, Errors errors) {
// name 不能为空
ValidationUtils.rejectIfEmpty(errors,"name","name.empty","name is null");
// age 不能小于0,不能大于200
Person 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.error","age>200");
}
}
}
4、进行测试
1、创建一个TestPerson.java
package com.atqt.spring6.vaalidator.one;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;
public class TestPerson {
public static void main(String[] args) {
// 创建person对象
Person person = new Person();
person.setName("aha");
person.setAge(2000);
// 创建person对应的databinder
DataBinder binder = new DataBinder(person);
// 设置校验器
binder.setValidator(new PersonValidator());
// 调用方法执行校验
binder.validate();
// 输出校验结果
BindingResult result = binder.getBindingResult();
System.out.println(result.getAllErrors());
}
}
2、第二种方式:Bean Validation注解实现
1、基本步骤

2、使用Bean Validation校验方式,就是如何将Bean Validation需要使用的javax.validation.ValidatorFactory 和javax.validation.Validator注入到容器中
3、spring默认有一个实现类LocalValidatorFactoryBean,它实现了上面Bean Validation中的接口,并且也实现了org.springframework.validation.Validator接口。
4、常用注解说明
| 注解 | 说明 |
|---|---|
| @NotNull | 限制必须不为null |
| @NotEmpty | 只作用于字符串类型,字符串不为空,并且长度不为0 |
| @NotBlank | 只作用于字符串类型,字符串不为空,并且trim()后不为空串 |
| @DecimalMax(value) | 限制必须为一个不大于指定值的数字 |
| @DecimalMin(value) | 限制必须为一个不小于指定值的数字 |
| @Max(value) | 限制必须为一个不大于指定值的数字 |
| @Min(value) | 限制必须为一个不小于指定值的数字 |
| @Pattern(value) | 限制必须符合指定的正则表达式 |
| @Size(max,min) | 限制字符长度必须在min到max之间 |
| 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
1、创建配置类,配置LocalValidatorFactoryBean
1、创建ValidationConfig.java
package com.atqt.spring6.vaalidator.two;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
@Configuration
@ComponentScan("com.atqt.spring6.vaalidator.two")
public class ValidationConfig {
@Bean
public LocalValidatorFactoryBean vaalidator(){
return new LocalValidatorFactoryBean();
}
}
2、创建实体类,使用注解定义校验规则
1、User.java
package com.atqt.spring6.vaalidator.two;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
public class User {
@NotNull
private 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;
}
}
3、校验器的实现
1、使用jakarta.validation.Validator校验
package com.atqt.spring6.vaalidator.two;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class MyValidation1 {
@Autowired
private Validator validator;
public boolean validatorByUser(User user){
Set<ConstraintViolation<User>> validate = validator.validate(user);
return validate.isEmpty();
}
}
2、使用org.springframework.validation.Validator校验
package com.atqt.spring6.vaalidator.two;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.validation.Validator;
import java.util.List;
@Service
public class MyValidation2 {
@Autowired
private Validator validator;
public boolean validatorByUserTwo(User user){
// 设置校验的错误
BindException bindException = new BindException(user,user.getName());
validator.validate(user,bindException);
List<ObjectError> allErrors = bindException.getAllErrors();
System.out.println(allErrors);
// 检测 看看是否有错误信息
return bindException.hasErrors();
}
}
4、测试
1、TestUser.java
package com.atqt.spring6.vaalidator.two;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestUser {
@Test
public void testCalidationOne(){
ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
MyValidation1 validation1 = context.getBean(MyValidation1.class);
// 创建一个User测试对象
User user = new User();
user.setName("啊哈哈哈");
boolean message = validation1.validatorByUser(user);
System.out.println(message);
}
@Test
public void testCalidationTwo(){
ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);
MyValidation2 validation2 = context.getBean(MyValidation2.class);
// 创建一个User测试对象
User user = new User();
user.setName("啊哈哈哈");
user.setAge(10);
boolean message = validation2.validatorByUserTwo(user);
System.out.println(message);
}
}
3、第三种方式:基于方法实现校验
1、创建配置类,配置MethodValidationPostProcessor
1、创建ValidationConfig.java
package com.atqt.spring6.vaalidator.three;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
@Configuration
@ComponentScan("com.atqt.spring6.vaalidator.three")
public class ValidationConfig {
@Bean
public MethodValidationPostProcessor validationPostProcessor(){
return new MethodValidationPostProcessor();
}
}
2、创建实体类,使用注解设置校验规则
1、创建User.java类
package com.atqt.spring6.vaalidator.three;
import jakarta.validation.constraints.*;
public class User {
@NotNull
private 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 getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = 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;
}
}
3、定义Service类,通过注解操作对象
1、创建MyService.java
package com.atqt.spring6.vaalidator.three;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Service
@Validated
public class MyService {
public String testMethod(@NotNull @Valid User user){
return user.toString();
}
}
4、进行测试
1、TestUser.java类
package com.atqt.spring6.vaalidator.three;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
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("哈哈");
user.setAge(50);
user.setPhone("2346");
service.testMethod(user);
}
}
4、第四种方法:实现自定义校验
1、就是自己写注解,然后根据注解进行校验
2、暂时跳过