java注解参数校验
java注解参数校验
1. @Validated和@Valid区别:
-
@Validated :
-
- 提供者:它是Spring框架的注解
- 的作用域:类、方法、参数
-
@valid :
-
- 提供者:他是javax提供的
- 作用域:方法、字段、构造方法、参数、TYPE_US
注:TYPE_USE:在 Java 8 之前的版本中,只能允许在声明式前使用 Annotation。而在 Java 8 版本中,Annotation 可以被用在任何使用 Type 的地方,例如:初始化对象时 (new),对象类型转化时,使用 implements 表达式时,或者使用 throws 表达式时。
//初始化对象时
String myString = new @Valid String();
//对象类型转化时
myString = (@Valid String) str;
//使用 implements 表达式时
class MyList<T> implements List<@Valid T> {...}
//使用 throws 表达式时
public void validateValues() throws @Valid ValidationFailedException{...}
2. 参数校验常用注解:
| 注解 | 验证的数据类型 | 备注 |
|---|---|---|
| Null | 任意类型 | 参数值必须是 Null |
| NotNull | 任意类型 | 参数值必须不是 Null |
| NotBlank | 只能作用于字符串 | 字符串不能为 null,而且字符串长度必须大于0,至少包含一个非空字符串 |
| NotEmpty | CharSequence Collection Map Array | 参数值不能为null,且不能为空 (字符串长度必须大于0,空字符串(“ ”)可以通过校验) |
| Size(min,max ) | CharSequence Collection Map Array | 字符串:字符串长度必须在指定的范围内 Collection:集合大小必须在指定的范围内 Map:map的大小必须在指定的范围内 Array:数组长度必须在指定的范围内 |
| Pattern(regexp) | 字符串类型 | 验证字符串是否符合正则表达式 |
| Min(value) | 整型类型 | 参数值必须大于等于 最小值 |
| Max(value) | 整型类型 | 参数值必须小于等于 最大值 |
| DecimalMin(value) | 整型类型 | 参数值必须大于等于 最小值 |
| DecimalMax(value) | 整型类型 | 参数值必须小于等于 最大值 |
| Positive | 数字类型 | 参数值为正数 |
| PositiveOrZero | 数字类型 | 参数值为正数或0 |
| Negative | 数字类型 | 参数值为负数 |
| NegativeOrZero | 数字类型 | 参数值为负数或0 |
| Digits(integer,fraction) | 数字类型 | 参数值为数字,且最大长度不超过integer位,整数部分最高位不超过fraction位 |
| AssertTrue | 布尔类型 | 参数值必须为 true |
| AssertFalse | 布尔类型 | 参数值必须为 false |
| Past | 时间类型(Date) | 参数值为时间,且必须小于 当前时间 |
| PastOrPresent | 时间类型(Date) | 参数值为时间,且必须小于或等于 当前时间 |
| Future | 时间类型(Date) | 参数值为时间,且必须大于 当前时间 |
| FutureOrPresent | 时间类型(Date) | 参数值为时间,且必须大于或等于 当前日期 |
| 字符串类型 | 被注释的元素必须是电子邮箱地址 |
Pattern注解校验 常用正则表达式
@Pattern(regexp = "^[1-9]]\\d*$", message = "XX参数值必须是正整数")
3. 分组
- @Validated :支持分组验证,可以更细致地控制验证过程。此外,由于它是Spring专有的,因此可以更好地与Spring的其他功能(如Spring的依赖注入)集成。
- @Valid:主要支持标准的Bean验证功能,不支持分组验证。
分组验证是为了在不同的验证场景下能够对对象的属性进行灵活地验证,从而提高验证的精细度和适用性。一般我们在对同一个对象进行保存或修改时,会使用同一个类作为入参。那么在创建时,就不需要校验id,更新时则需要校验用户id,这个时候就需要用到分组校验了。
对于定义分组有两点要特别注意:
-
- 定义分组必须使用接口。
- 要校验字段上必须加上分组,分组只对指定分组生效,不加分组不校验。
有这样一个需求,在创建用户时校验用户名,修改用户时校验用户id。下面对我们对这个需求进行一个简单的实现。
- 创建分组
CreationGroup 用于创建时指定的分组:
public interface CreationGroup {
}
UpdateGroup 用于更新时指定的分组:
public interface UpdateGroup {
}
- 创建用户类
创建一个UserBean用户类,分别校验 username 字段不能为空和id字段必须大于0,然后加上CreationGroup和 UpdateGroup 分组。
@Data
public class UserBean {
@NotEmpty( groups = {CreationGroup.class})
private String username;
@Min(value = 18)
private Integer age;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 1 ,groups = {UpdateGroup.class})
private Long id;
}
- 创建接口
在ValidationController 中新建两个接口 updateUser 和 createUser:
@RestController
@RequestMapping("validation")
public class ValidationController {
@GetMapping("createUser")
public UserBean createUser(@Validated({CreationGroup.class}) UserBean userBean){
return userBean;
}
@GetMapping("updateUser")
public UserBean updateUser(@Validated({UpdateGroup.class}) UserBean userBean){
return userBean;
}
}
没有设置分组的属于默认分组 Default.class
4. 嵌套验证
- @Validated :不支持嵌套验证。
- @Valid:支持嵌套验证,可以嵌套验证对象内部的属性。
介绍嵌套校验之前先看一下两个概念:
- 嵌套校验(Nested Validation) 指的是在验证对象时,对对象内部包含的其他对象进行递归验证的过程。当一个对象中包含另一个对象作为属性,并且需要对这个被包含的对象也进行验证时,就需要进行嵌套校验。
- 嵌套属性指的是在一个对象中包含另一个对象作为其属性的情况。换句话说,当一个对象的属性本身又是一个对象,那么这些被包含的对象就可以称为嵌套属性。
有这样一个需求,在保存用户时,用户地址必须要填写。下面来简单看下示例:
- 创建地址类 AddressBean
在AddressBean 设置 country和city两个属性为必填项。
@Data
public class AddressBean {
@NotBlank
private String country;
@NotBlank
private String city;
}
- 修改用户类,将AddressBean作为用户类的一个嵌套属性
特别提示:想要嵌套校验生效,必须在嵌套属性上加 @Valid 注解。
@Data
public class UserBean {
@NotEmpty(groups = {CreationGroup.class})
private String username;
@Min(value = 18)
private Integer age;
private String email;
@Min(value = 1 ,groups = {UpdateGroup.class})
private Long id;
//嵌套验证必须要加上@Valid
@Valid
@NotNull
private AddressBean address;
}
- 创建一个嵌套校验测试接口
@PostMapping("nestValid")
public UserBean nestValid(@Validated @RequestBody UserBean userBean){
System.out.println(userBean);
return userBean;
}

浙公网安备 33010602011771号