背景
JSR 303 – Bean Validation 是一个数据验证的规范,2009 年 11 月确定最终方案。 Hibernate Validator 是 Bean Validation 的参考实现 . Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 我们通常写接口时会对传来的参数进行校验判断,比如字符串非空判断,值在多少返回等,这些就要用到Spring 的参数校验,这里我们使用在spring-boot-starter-web包里面有hibernate-validator包, 参数校验有几种方式,如下
- 1.使用@Valid+BindingResult
- 2.注解使用@Valid +全局异常捕捉处理
下面来介绍这两种方式的使用
使用@Valid+BindingResult 参数验证
1.符合国际JSP 303规范,先定义个Bean,别人在字段名上添加验证的注解,@NotBlank 字段名不能为null,同时长度大于0常有的校验类型有
Constraint 详细信息
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
复制代码
/**
* @author Lang.Chen
* @date 2018/6/20 下午4:39
*/
public class User {
//账号
@NotBlank(message = "账号不能为空")
private String phone;
//密码
@NotBlank(message = "密码不能为空")
private String password;
public void setPhone(String phone) {
this.phone = phone;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public String getPassword() {
return password;
}
}
复制代码
2.在Controller类里面对相应的接口添加@Valid+BindingResult验证,加完以后,如果参数验证不通过,那就直接进入if语句里面,在语句里面做相应的返回结果
if(bindingResult.hasErrors()){
}
复制代码
@RestController
@RequestMapping(value = "/user")
public class UserController implements IUser {
@Override
@RequestMapping(value = "/login", method = RequestMethod.POST)
public User login( @Valid User userInfo, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
System.out.print(bindingResult.getFieldError().getDefaultMessage());
return null;
}
return userInfo;
}
}
复制代码
好了,第一种验证我们已经说完了,但你仔细想想,如果我有多个接口,是不是每次有要写@Valid+BindgResult bingingResult,然后再到If语句里面进行判断,如果仅仅是错误信息不一致,但返回的客户端结构是一致的,比如
{"code":"1002","message":"parameters are missing","data":"{}"}
复制代码
不同的验证只要改变message,那么是不是可以统一处理,来减少代码量,于是下面介绍第二种方式
使用@Valid+全局异常捕捉 参数校验
简单点说,由第一种方式去掉BindingResult,然后再定义一个全局异常类,同样的
1.还是定义POJO
/**
* @author Lang.Chen
* @date 2018/6/20 下午4:39
*/
public class User {
//账号
@NotBlank(message = "账号不能为空")
private String phone;
//密码
@NotBlank(message = "密码不能为空")
private String password;
public void setPhone(String phone) {
this.phone = phone;
}
public void setPassword(String password) {
this.password = password;
}
public String getPhone() {
return phone;
}
public String getPassword() {
return password;
}
}
复制代码
2.在Controller里面的方法定义要验证的@Valid
public class UserController implements IUser {
@Override
@RequestMapping(value = "/login2", method = RequestMethod.POST)
public User login2(@RequestBody @Valid User userInfo) {
return null;
}
}
复制代码
3.定义全局异常类
所有验证失败的结果都会在GlobleExceptionHandler的defultExcepitonHandler方法里面捕捉到
@RestControllerAdvice
@Component
public class GlobleExceptionHandler {
@ResponseBody
@ExceptionHandler(Exception.class)
public String defultExcepitonHandler(Exception ex) {
ex.printStackTrace();
if(ex instanceof BindException){
//处理返回的错误信息
StringBuffer errorMsg = new StringBuffer();
BindException c = (BindException) ex;
List<ObjectError> errors = c.getBindingResult().getAllErrors();
for (ObjectError error : errors) {
errorMsg.append(error.getDefaultMessage()).append(";");
}
return errorMsg.toString();
}
return "";
}
}
复制代码
有关于自定义验证和分组验证,就不一一介绍了,会使用以上2个就可以了。
Q&A
1.如何使用单个参数验证,并且进入全局异常捕捉,返回?
有时候只传入少数验证时,我们不可能都是新建一个对象来接受,这时候如何使用单个参数验证呢,看到网上使用在类上添加 @Validated参数,然后通过全局异常捕捉方式
@RestController
@RequestMapping("/order")
@Validated
public class OrderController implements IOrder {
@RequestMapping(value = "/byId",method = RequestMethod.POST)
public OrderInfo byId( @Max(value = 50) int orderId) {
return null;
}
}
复制代码
但每次访问接口时,都是报同一个错误,就没用这个方式了,如果有人找到解决方案,请指教,谢谢
{
"timestamp": "2018-06-24T07:09:14.235+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/order/byId"
}
复制代码
@Valid和@Validated的区别
@Valid是javax.validation里的 @Validated是@Valid 的一次封装,是Spring提供的校验机制使用。@Validated 提供分组功能
作者:飞一样的猪
链接:https://juejin.im/post/5b2f4514f265da597a6108f8
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。