Springboot统一参数验证方式
Springboot统一验证方式
在提供http api 接口形式的服务中,通过都会传递参数为一个对象。我们需要对这个对象的各个字段进行校验。来判断是否为合法值。
传统的方式为自己获取每个字段的值,自己写方法进行判断。
这种方式太过麻烦。
推荐使用
推荐使用 validation 通过其JSR303 Java 规范提案 的验证方法来进行验证。进行简化。
@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
如不满足还可以自定义验证注解。
使用方式:
public class user
{
@NotNull(message = "姓名不可为空")
private String name;
@DecimalMin(value = "100",message = "年龄必须大于100")
private Integer age;
}
public user create(@RequestBody @Valid user u) {}
这里有个问题,@Valid 如果有验证不通过的约束。将会抛出一个异常,这个异常将直接响应。
响应json结构:
{
"timestamp": 1554169655057,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"errors": [
{
"codes": [
"NotNull.user.name",
"NotNull.name",
"NotNull.java.lang.String",
"NotNull"
],
"arguments": [
{
"codes": [
"user.name",
"name"
],
"arguments": null,
"defaultMessage": "name",
"code": "name"
}
],
"defaultMessage": "姓名不可为空",
"objectName": "user",
"field": "name",
"rejectedValue": null,
"bindingFailure": false,
"code": "NotNull"
}
],
"message": "Validation failed for object='user'. Error count: 1",
"path": "/a"
}
这种方式在http api 的情况下非常不优化。
验证异常统一处理拦截器
我们可以提供自定义异常拦截器来实现对这个异常的补货,返回统一约定的响应结构体。
@ControllerAdvice
public class ExceptionControllerAdvice
{
/**
* 对验证约束异常进行拦截,返回约定的响应体
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public ResponseEntity bindExceptionHandler(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
List<ObjectError> errors = bindingResult.getAllErrors();
StringBuffer buffer = new StringBuffer();
for (ObjectError error : errors) {
buffer.append(error.getDefaultMessage()).append(" ");
}
return new ResponseEntity("403", buffer.toString());
}
/**
* 参数类型转换错误
*/
@ExceptionHandler(HttpMessageConversionException.class)
@ResponseBody
public ResponseEntity parameterTypeException(HttpMessageConversionException exception) {
return new ResponseEntity("403", exception.getCause().getLocalizedMessage());
}
}
这样我们就可以简化对请求参数的校验了。