@Valid注解使用
1.导入hibernate-validator包:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>5.2.2.Final</version> </dependency>
2. 注解使用位置
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
3. 嵌套验证
在比较两者嵌套验证时,先说明下什么叫做嵌套验证。比如我们现在有个实体叫做Item:
public class Item {
@NotNull(message = "id不能为空")
@Min(value = 1, message = "id必须为正整数")
private Long id;
@NotNull(message = "props不能为空")
@Size(min = 1, message = "至少要有一个属性")
private List<PO> POS;
}
Item带有很多属性,属性里面有属性id,属性值id,属性名和属性值,如下所示:
public class PO {
@NotNull(message = "pid不能为空")
@Min(value = 1, message = "pid必须为正整数")
private Long pid;
@NotNull(message = "vid不能为空")
@Min(value = 1, message = "vid必须为正整数")
private Long vid;
@NotBlank(message = "pidName不能为空")
private String pidName;
@NotBlank(message = "vidName不能为空")
private String vidName;
}
属性这个实体也有自己的验证机制,比如属性和属性值id不能为空,属性名和属性值不能为空等。
现在我们有个ItemController接受一个Item的入参,想要对Item进行验证,如下所示:
@RestController
public class ItemController {
@PostMapping("/item/add")
public void addItem(@Validated Item item) {
doSomething();
}
}
在上图中,如果Item实体的props属性不额外加注释,只有@NotNull和@Size,无论入参采用@Validated还是@Valid验证,Spring Validation框架只会对Item的id和props做非空和数量验证,不会对POS字段里的PO实体进行字段验证,也就是@Validated和@Valid加在方法参数前,都不会自动对参数进行嵌套验证。也就是说如果传的List中有PO的pid为空或者是负数,入参验证不会检测出来。
为了能够进行嵌套验证,必须手动在Item实体的props字段上明确指出这个字段里面的实体也要进行验证。由于@Validated不能用在成员属性(字段)上,但是@Valid能加在成员属性(字段)上,而且@Valid类注解上也说明了它支持嵌套验证功能,那么我们能够推断出:@Valid加在方法参数时并不能够自动进行嵌套验证,而是用在需要嵌套验证类的相应字段上,来配合方法参数上@Validated或@Valid来进行嵌套验证。
4.分组验证
在自定义注解@Validated中
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Validated {
Class<?>[] value() default {};
}
定义了一个Class[]数组用来分组.这样我们就可以引入分组校验的概念,首先根据需要的分组新建自己的接口.
public class ValidExampleVO implements Serializable{
//更新分组
public interface Update{}
//添加分组
public interface Add{}
@Null(message="必须为空",groups=Add.class)
private String nustNull;
@NotNull(message="必须不为空",groups={Update.class})
private String notNull;
//集合对象的元素不为0,即集合不为空,也可以用于字符串不为null
@NotEmpty(message="集合不为空")
private List<String> notEmpty;
//只能用于字符串不为null
@NotBlank(message="字符不能为空")
private String notBlank;
@Max(message="最大值不超过10",value = 10)
@Min(message="最小值不小于5",value = 5)
private Integer maxMin;
//支持java类型String,Collection,Map,arrays,CharSequence
@Size(message="范围2-5",max = 5,min=2)
private String size;
//支持java类型String
@Length(message="长度范围2-5",min=2,max=5)
private String length;
@Past(message="必须是过去的日期")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date past;
@Future(message="必须是未来的日期")
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date future;
@Email(message="必须是Email格式")
private String email;
@AssertTrue(message="必须为真")
private Boolean nustTrue;
@AssertFalse(message="必须为假")
private Boolean nustFalse;
}
然后在需要校验的bean上加入分组,根据需要,在Controller处理请求中加入@Validated注解并引入需要校验的分组.
@RestController
@RequestMapping("/validExample")
public class ValidExampleController {
@PostMapping(value = "/add")
//@Validated 才有分组功能
public void add(@RequestBody @Validated(Add.class) ValidExampleVO vo) {
doSomething();
}
@PostMapping(value = "/update")
public void update(@RequestBody @Validated(Update.class) ValidExampleVO vo) {
doSomething();
}