谈起校验就不得不说@Valid和@Valitdated的区别
①:分组验证
②:注解位置
③:嵌套验证
这里着重谈一下嵌套验证。
什么是嵌套验证?
这个是一个登录信息,它里面可能包含用户信息
//登录信息
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class LoginUser {
//用户名
@NotNull(message = "用户名不能为空")
@Min(value = 2, message = "用户名必须大于两位")
private String username;
//密码
@NotNull(message = "密码不能为空")
@Min(value = 6, message = "密码必须大于六位")
private String password;
//用户信息
@NotNull(message = "用户信息不能为空")
private Set<User> roles;
}
//用户信息
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class User {
//身份证号
@NotNull(message = "身份证号不能为空")
private String roleId;
//地址
@NotNull(message = "地址不能为空")
private String ipAddr;
}
↓此刻如果在controller方法形参前无论是加@Validated或者Valid,Spring只会对用户名,密码,和用户信息校验,但是,,不会对用户信息里面的身份证号以及地址进行非空校验。
@RestController
@RequestMapping(value = "/person")
public class CheckUser {
@PostMapping(value="/checkK")
public String checkU(@Validated @RequestBody LoginUser loginUser, BindingResult bindingResult) {
//TODO
return null;
}
}
如果想嵌套校验,怎么解决呢↓
在用户信息属性上写@Valid的注解(注意:这里不能写@Validated,原因在上面写着:@Validated不可以加在成员属性上)
//用户信息
@Valid // 嵌套验证必须用@Valid
@NotNull(message = "用户信息不能为空")
private Set<User> roles;
了解以上区别之后,再讲一下springboot的校验机制。
校验机制主要有两种
①:SpringMVC校验(↑的校验方式就是这种)
②:AOP校验
区别:
先后顺序:
SpringMVC校验→AOP校验
!!注意:如果形参前面是@RequestBody+@Validated的话,校验失败时抛得异常是MethodArgumentNotValidException而不是BindException。当形参只有@Validated的话抛的是BindException
验证一下结论:首先写一个全局异常处理
@RestControllerAdvice
public class ExceptionAdivce {
//AOP校验
@ResponseBody
@ExceptionHandler(value= ConstraintViolationException.class)
public Map erroHandleAop(ConstraintViolationException ex){
Map map = new HashMap();
map.put("message",ex.getMessage());
return map;
}
//spring校验(@RequestBody+@Validated)
@ResponseBody
@ExceptionHandler(value= MethodArgumentNotValidException.class)
public Map erroHandleSpring(MethodArgumentNotValidException ex){
Map map = new HashMap();
map.put("message",ex.getMessage());
return map;
}
//spring校验(@Validated)
@ResponseBody
@ExceptionHandler(value= BindException.class)
public Map erroHandleSpring1(BindException ex){
Map map = new HashMap();
map.put("message",ex.getMessage());
return map;
}
}
①:AOP
//AOP
@Validated
@RestController
@RequestMapping(value = "/person")
public class CheckUser {
@PostMapping(value="/checkK")
public String checkU( @Valid LoginUser loginUser,BindingResult result) {
//TODO
return null;
}
}
②:Valid
//Valid
@RestController
@RequestMapping(value = "/person")
public class CheckUser {
@PostMapping(value="/checkK")
public String checkU( @Valid LoginUser loginUser) {
//TODO
return null;
}
}
③:Valid+RequestBody
//Valid+RequestBody
@RestController
@RequestMapping(value = "/person")
public class CheckUser {
@PostMapping(value="/checkK")
public String checkU( @Valid @RequestBody LoginUser loginUser) {
//TODO
return null;
}
}
先后顺序验证:在postman里故意把这里面既有springmvc校验和AOP校验都不符合,看看先走哪一个?
//这里面既有springmvc校验和AOP校验
@Validated
@RestController
@RequestMapping(value = "/person")
public class CheckUser {
@PostMapping(value="/checkK")
public String checkU(@Valid @RequestBody LoginUser loginUser, @NotNull String ip) {
//TODO
return null;
}
}
答案出来了,先走的spring校验
文章评论