推荐我的另一篇博文:《
利用Aspect/Javassist/动态代理/Lombok等方式省略Controller的参数校验结果处理代码
》。
Validation的注解就不介绍了,大家可以去看源码包或者网上找相关资料。
这里直接说执行校验的3种方式。本文使用的
参数注解情况
以及
请求的参数值
如下
/**
* 用户类
* @author z_hh
* @time 2019年4月21日
*/
@Data
public class User {
/** id */
@NotNull(message="id不能为空")
private Long id;
/** 姓名 */
@NotBlank(message="姓名不能为空")
private String name;
/** 年龄 */
@NotNull(message="年龄不能为空")
@Max(message="年龄不能超过120岁", value = 120)
@Min(message="年龄不能小于1岁", value = 1)
private Integer age;
/** 创建时间 */
@Future
private Date createTime;
}
{
"id": 12,
"name": "",
"age": 0,
"createTime": "2018-12-31"
}
第一种:在Controller方法参数前加@Valid注解——校验不通过时直接抛异常
/**
* 校验不通过时直接抛异常
* @param user
* @return
*/
@PostMapping("/test1")
public Object test1(@RequestBody @Valid User user) {
return "操作成功!";
}
调用时会抛出一个org.springframework.web.bind.MethodArgumentNotValidException异常:
2019-04-21 11:35:28.600 WARN 10852 — [nio-8080-exec-4] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.
MethodArgumentNotValidException
: Validation failed for argument [0] in public java.lang.Object com.example.validation.UserController.test1(com.example.validation.User) with 3 errors: [Field error in object ‘user’ on field ‘createTime’: rejected value [Mon Dec 31 08:00:00 CST 2018]; codes [Future.user.createTime,Future.createTime,Future.java.util.Date,Future]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.createTime,createTime]; arguments []; default message [createTime]]; default message [
需要是一个将来的时间
]] [Field error in object ‘user’ on field ‘age’: rejected value [0]; codes [Min.user.age,Min.age,Min.java.lang.Integer,Min]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],1]; default message [
年龄不能小于1岁
]] [Field error in object ‘user’ on field ‘name’: rejected value []; codes [NotBlank.user.name,NotBlank.name,NotBlank.java.lang.String,NotBlank]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.name,name]; arguments []; default message [name]]; default message [
姓名不能为空
]] ]
★★★使用这种的话一般结合统一异常处理器(或者Aspect、拦截器等)处理
★★★
第二种:
在Controller方法参数前加@Valid注解,参数后面定义一个BindingResult类型参数——执行时会将校验结果放进bindingResult里面,用户自行判断并处理
/**
* 将校验结果放进BindingResult里面,用户自行判断并处理
* @param user
* @param bindingResult
* @return
*/
@PostMapping("/test2")
public Object test2(@RequestBody @Valid User user, BindingResult bindingResult) {
// 参数校验
if (bindingResult.hasErrors()) {
String messages = bindingResult.getAllErrors()
.stream()
.map(ObjectError::getDefaultMessage)
.reduce((m1, m2) -> m1 + ";" + m2)
.orElse("参数输入有误!");
throw new IllegalArgumentException(messages);
}
return "操作成功!";
}
第三种:用户手动调用对应API执行校验——Validation.buildDefault ValidatorFactory().getValidator().validate(xxx)
/**
* 用户手动调用对应API执行校验
* @param user
* @return
*/
@PostMapping("/test3")
public Object test3(@RequestBody User user) {
// 参数校验
validate(user);
return "操作成功!";
}
private void validate(@Valid User user) {
Set<ConstraintViolation<@Valid User>> validateSet = Validation.buildDefaultValidatorFactory()
.getValidator()
.validate(user, new Class[0]);
if (!CollectionUtils.isEmpty(validateSet)) {
String messages = validateSet.stream()
.map(ConstraintViolation::getMessage)
.reduce((m1, m2) -> m1 + ";" + m2)
.orElse("参数输入有误!");
throw new IllegalArgumentException(messages);
}
}
喜欢使用哪一种看你喜欢咯?