springmvc整合validation(二) @valid与@validated的区别
在上一篇中( springmvc整合validation(一) ),梳理了如何整合validation校验框架。本篇我们梳理一下@valid和@validated的区别。
在检验入参是否符合规范时,使用@Validated或者@Valid在基本验证功能上没有太多区别。但是在分组、注解地方、嵌套验证等功能上两个注解会有所不同。
1.分组校验
@Validated提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。没有添加分组属性时,默认验证没有分组的验证属性。
使用场景举例:一个DTO类,有一个id的属性,我们希望在insert的时候id为空,在update和delete的时候,id不能为空。
本篇内容是在( springmvc整合validation(一) )的基础上实现,具体实现如下:
1.1新增groups
我们首先新增insert、update、delete三个group。注意,group必须为接口。
package com.hjj.demo.validate; public interface ValidateGroups { public interface InsertGroup{ } public interface UpdateGroup{ } public interface DeleteGroup{ } }
1.2使用group
在ValidateTestDTO类的id属性上使用group。
@NotNull(groups = {ValidateGroups.UpdateGroup.class,ValidateGroups.DeleteGroup.class}) @Null(groups = {ValidateGroups.InsertGroup.class}) public Long id;
期望达到的目前,在update和delete的时候id不能为空,在insert的时候id必须为空。
1.3修改controller代码
package com.hjj.demo.validate; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; @RestController public class ValidateTestController{ @PostMapping( value = "/insertTest",produces= MediaType.APPLICATION_JSON_VALUE) public String insert(@RequestBody @Validated(ValidateGroups.InsertGroup.class) ValidateTestDTO validateTestDTO){ return "insert OK"; } @PostMapping( value = "/updateTest",produces= MediaType.APPLICATION_JSON_VALUE) public String update(@RequestBody @Validated(ValidateGroups.UpdateGroup.class) ValidateTestDTO validateTestDTO){ return "update OK"; } @PostMapping( value = "/deleteTest",produces= MediaType.APPLICATION_JSON_VALUE) public String delete(@RequestBody @Validated(ValidateGroups.DeleteGroup.class) ValidateTestDTO validateTestDTO){ return "delete OK"; } @PostMapping( value = "/test",produces= MediaType.APPLICATION_JSON_VALUE) public String test(@RequestBody @Valid ValidateTestDTO validateTestDTO){ return "test OK"; } }
如上代码所示,我们新增3个接口,分别模拟insert、update、delete的场景。这里有一个地方要注意,分组校验只有@validated注解才支持,所以我们使用@validated注解,并且注解里面加上期望校验的group。
1.4测试
insert场景:
update场景:
delete场景:
从以上的3个测试用例可以看出,满足我们的校验需求。
2.注解使用的地方
@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上
@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上
两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。
3.嵌套校验
在上一篇中,我们已经介绍了@valid注解的嵌套校验。那么问题来了,@validated不支持用在成员变量上面,怎么实现嵌套校验呢?
其实很简单,成员变量上面还是使用@valid注解,但是在controller上面我们使用@validated注解,这样就即支持分组校验,也支持嵌套校验了。
测试代码如下
ValidateTestDTO中增加以下代码:
@NotNull @Valid //这里还是使用valid注解 public ValidateLevel2DTO dto; public ValidateLevel2DTO getDto() { return dto; } public void setDto(ValidateLevel2DTO dto) { this.dto = dto; }
修改controller代码,使用@validated注解:
@PostMapping( value = "/test",produces= MediaType.APPLICATION_JSON_VALUE) public String test(@RequestBody @Validated ValidateTestDTO validateTestDTO){ return "test OK"; }
测试:
从测试结果可以看出,嵌套校验正常工作。
4.总结
最后,我们总结一下。
1)@validated支持分组校验,@valid不支持
2)@validated和@valid使用的地方不一样
3)@Validated:用在方法入参上无法单独提供嵌套验证功能。不能用在成员属性(字段)上。能配合嵌套验证注解@Valid进行嵌套验证。
@Valid:用在方法入参上无法单独提供嵌套验证功能。能够用在成员属性(字段)上。能配合嵌套验证注解@Valid进行嵌套验证。



