1、简介
- 数据校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据。
- 使用Validator进行数据校验有利于提高代码可读性、可维护性,还不会导致我们代码业务冗杂。
2、Vaildator常用注解
JSR 提供的校验注解:
@Null
被注释的元素必须为 null@NotNull
被注释的元素必须不为 null@AssertTrue
被注释的元素必须为 true@AssertFalse
被注释的元素必须为 false@Min(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值@DecimalMin(value)
被注释的元素必须是一个数字,其值必须大于等于指定的最小值@DecimalMax(value)
被注释的元素必须是一个数字,其值必须小于等于指定的最大值@Size(max=, min=)
被注释的元素的大小必须在指定的范围内@Digits (integer, fraction)
被注释的元素必须是一个数字,其值必须在可接受的范围内@Past
被注释的元素必须是一个过去的日期@Future
被注释的元素必须是一个将来的日期@Pattern(regex=,flag=)
被注释的元素必须符合指定的正则表达式
Hibernate Validator 提供的校验注解:
@NotBlank(message =)
验证字符串非 null,且长度必须大于 0@Length(min=,max=)
被注释的字符串的大小必须在指定的范围内@NotEmpty
被注释的字符串的必须非空@Range(min=,max=,message=)
被注释的元素必须在合适的范围内
3、使用步骤
3.1 使用前需要注意的细节
- 因为我们是基于 Spring Boot 经行测试,其实只需要到入
spring-boot-starter-web
依赖即可(该依赖已经包含了Valiator校验的所有依赖),但是自从Spring Boot 2.3.1
之后Validator
的依赖已经被从中剔除了,所有想要使用Validator
校验需要手动导入Validation
依赖。
3.2 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
3.3 创建测试实体对象
使用方式: 使用检验注解修饰对象属性(按自己需要选择修饰注解)
注意: 这里使用了3个自定义注解后面补充讲解(不懂的可以先注释掉)。
/**
* 差数校验测试实体对象
*
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 13:57
*/
@Data
public class LoginBody
{
@Size(min = 3, max = 11, message = "用户名长度3-11")
@UsernameCheck //自定义注解
private String username;
@Size(min = 3, max = 11, message = "密码长度3-64")
@PasswordCheck //自定义注解
private String password;
/** 自定义注解使用 */
@PhoneCheck //自定义注解
private String phoneNumber;
@Email(message = "邮箱格式有误!")
private String email;
}
3.4 创建Controller测试类
使用方式:
- 校验实体对象,使用
@Valid
注解配置@RequestBody
注解开启实体对象属性值校验。 - 直接在方法上面进行参数校验,在类上使用
@Validtor
开启controller方法参数校验,然后在需要经行校验的位置自行选择校验注解。
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/21 19:11
*/
@Validated //在该controller开启参数校验
@RestController
public class TestController
{
/**
* 使用 @Valid 注解配合 @RequestBody 注解开启实体对象参数校验
*
* @param body
* @return
*/
@PostMapping("test01")
public Object test01(@Valid @RequestBody LoginBody body)
{
return body;
}
/**
* 直接在方法参数里面使用参数校验
*
* @param name 参数
* @param address 参数
* @return 结果
*/
@GetMapping("test02")
public Object test02(
@NotBlank(message = "名称不能为空")
@RequestParam(required = true, value = "name") String name,
@NotBlank(message = "地址信息不能为空")
@RequestParam(required = true, value = "address") String address
)
{
return name+": "+address;
}
}
3.5 使用Postmen测试
3.6 自定义校验注解
作用: 自定义校验规则。
1、自定义手机号码校验注解和校验规则实现类
注解:@PhoneCheck
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 14:08
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Constraint(validatedBy = PhoneCheckValidator.class) //自定义校验类
@Documented
public @interface PhoneCheck
{
/** 失败提示信息 */
String message() default "手机号码格式有误!";
/** 默认开启手机号码校验 */
boolean required() default true;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现类:PhoneCheckValidator
/**
* 自定义手机号码校验规则
* 1、需要实现 ConstraintValidator 接口,并重写 isValid 方法和 initialize 方法(initialize用到可以重写)。
*
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 14:12
*/
public class PhoneCheckValidator implements ConstraintValidator<PhoneCheck, String>
{
/** 手机号码是否填写:true(必须填)、false(不用填) */
private boolean required;
private final String CHECK_PHONE_NUMBER = "^[1]((3[0-9])|(4[5-9])|(5[0-3,5-9])|([6][5,6])|(7[0-9])|(8[0-9])|(9[1,8,9]))\\d{8}$";
/**
* 初始化参数
*
* @param constraintAnnotation 注解
*/
@Override
public void initialize(PhoneCheck constraintAnnotation)
{
required=constraintAnnotation.required();
}
/**
* 自定义校验规则
*
* @param phoneValue 检验的参数
* @param context 约束验证器上下文
* @return 校验结果
*/
@Override
public boolean isValid(String phoneValue, ConstraintValidatorContext context)
{
System.out.println("----------------手机号码校验---------------");
if (!required)
{
return true;
}
return phoneValue.matches(CHECK_PHONE_NUMBER);
}
}
2、自定义用户名校验注解和校验规则实现类
注解:@UsernameCheck
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 14:08
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Constraint(validatedBy = UsernameCheckValidator.class) //自定义校验类
@Documented
public @interface UsernameCheck
{
String message() default "用户名格式由数字和26个英文字母组成!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现类:UsernameCheckValidator
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 14:12
*/
public class UsernameCheckValidator implements ConstraintValidator<UsernameCheck, String>
{
//由数字和26个英文字母组成的字符串
private final String CHECK_USERNAME = "^[A-Za-z0-9]+$";
@Override
public boolean isValid(String phoneValue, ConstraintValidatorContext context)
{
System.out.println("----------------用户名校验---------------");
return phoneValue.matches(CHECK_USERNAME);
}
}
3、自定义密码校验注解和校验规则实现类
注解:@PasswordCheck
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 14:08
*/
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Constraint(validatedBy = PasswordCheckValidator.class) //自定义校验类
@Documented
public @interface PasswordCheck
{
String message() default "密码格式由数字和26个英文字母组成!";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
实现类:PasswordCheckValidator
/**
* @author cms
* @version 1.0.0.0
* @Date: 2022/5/22 15:51
*/
public class PasswordCheckValidator implements ConstraintValidator<PasswordCheck, String>
{
//由数字和26个英文字母组成的字符串
private final String CHECK_PASSWORD = "^[A-Za-z0-9]+$";
@Override
public boolean isValid(String phoneValue, ConstraintValidatorContext context)
{
System.out.println("----------------密码校验---------------");
return phoneValue.matches(CHECK_PASSWORD);
}
}
4、提示
- 本测试项目配合了统一结果返回 + 异常拦截一起使用,有兴趣的可以去看看我写的统一结果处理全局异常拦截那篇。
- 地址:
https://blog.csdn.net/qq_41135440/article/details/124901853?spm=1001.2014.3001.5501