前言
做web开发有一点很烦人就是要校验参数,基本上每个接口都要对参数进行校验,比如一些格式校验、非空校验都是必不可少的。如果参数比较少的话还是容易处理,但参数比较多了的话代码中就会出现大量的IF ELSE就比如下面这样: 这个例子只是校验了一下空参数。如果需要验证邮箱格式和手机号格式校验的话代码会更多,所以介绍一下validator通过注解的方式进行校验参数。
什么是Validator
Bean Validation
是Java定义的一套基于注解的数据校验规范,定义于JSR 303规范(JAVA EE6的字规范)。
Hibernate Validator
是Bean Validation的参考实现,提供了JSR-303 规范中所有内置constraint的实现,除此之外Hibernate Validator
还附加了一些constraint。
在SpringBoot
(2.3以下版本)中已经集成在 starter-web中,所以无需在添加其他依赖。在Springboot
2.3以上版本需单独引入:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
注解介绍
| 分组 | 注解
| 详细信息
| 备注 | | --- | --- | --- | --- | |
空和非空校验 | @Null | 被注释的元素必须为 null | | | | @NotNull | 被注释的元素必须不为 null | | | | @NotBlank | 验证字符串非null,且长度必须大于0 | Hibernate Validator 附加的 constraint | | | @NotEmpty | 被注释的字符串的必须非空 | Hibernate Validator 附加的 constraint | |
布尔值校验 | @AssertTrue | 被注释的元素必须为 true | | | | @AssertFalse | 被注释的元素必须为 false | | |
数值校验 | @Min(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 | | | | @Max(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | | | | @DecimalMin(value) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 | | | | @DecimalMax(value) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 | | | | @Size(max, min) | 被注释的元素的大小必须在指定的范围内 | | | | @Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 | | | | @Negative | 必须为负整数 | | | | @Positive | 必须为正整数 | | |
日期校验 | @Past | 被注释的元素必须是一个过去的日期 | | | | @PastOrPresent | 被注释的元素必须是当前或过去的日期 | | | | @Future | 被注释的元素必须是一个将来的日期 | | | | @FutureOrPresent | 被注释的元素必须是一个当前或将来的日期 | | |
其他 | @Pattern(value) | 被注释的元素必须符合指定的正则表达式 | | | | @Email | 被注释的元素必须是电子邮箱地址 | Hibernate Validator 附加的 constraint |
注意:
- @NotNull 适用于任何类型,被注解的元素必须不能与NULL
- @NotEmpty 适用于String、collection、Map或者数组,不能为Null且长度必须大于0 (String可以为空字符串)
- @NotBlank 只能用于String上面,不能为null,也不能为纯空格的字符串
使用
实体类校验
模拟用户注册封装了一个UserDTO 然后需要在controller方法体添加@Validated不加@Validated校验会不起作用
参数校验
在开发的时候一定遇到过单个参数的情况,在参数前面加上注解即可
@PostMapping("/get")
public ReturnVO getUserInfo(@RequestParam("userId") @NotNull(message = "用户ID不能为空") String userId){
//...
}
正则校验
使用正则校验手机号
/**
* 手机号
*/
@NotNull(message = "手机号不能为空")
@NotBlank(message = "手机号不能为空")
@Pattern(regexp ="^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
@Max(value = 11,message = "手机号只能为{max}位")
@Min(value = 11,message = "手机号只能为{min}位")
private String mobileNo;
自定义注解
上面的注解只有这么多,如果有特殊校验的参数我们可以使用Validator自定义注解进行校验。 首先创建一个IdCard注解:
@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {
String message() default "身份证号码不合法";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
在UserDTO中添加@IdCard
注解即可验证,在运行时触发。 然后添加IdCardValidator
主要进行验证逻辑 上面调用了is18ByteIdCardComplex
方法,传入参数就是手机号。
然后使用在实体类中使用:
@NotNull(message = "身份证号不能为空")
@IdCard(message = "身份证不合法")
private String IdCardNumber;
分组
就比如上面我们定义的UserDTO中的参数如果要服用的话怎么办? 在重新定义一个类然后里面的参数要重新添加注解? Validator提供了分组方法完美了解决实体类校验复用问题。
1.先创建分组的接口:
public interface Create extends Default { }
2.在注解加入分组参数:
/**
* 用户名
*/
@NotBlank(message = "用户姓名不能为空",groups = Create.class)
@NotNull(message = "用户姓名不能为空",groups = Create.class)
private String userName;
@NotBlank(message = "邮箱不能为空",groups = Update.class)
@NotNull(message = "邮箱不能为空",groups = Update.class)
@Email(message = "邮箱格式错误",groups = Update.class)
private String email;
3.然后在修改Controller在@Validated中传入Create.class
@PostMapping("/user")
public ReturnVO userRegistra(@RequestBody @Validated(Create.class) UserDTO userDTO){
ReturnVO returnVO = userService.userRegistra(userDTO);
return returnVO ;
}