1、为什么要使用Validation
在开发过程中有没有使用一堆的if来判断字段是否为空、电话号码是否正确、某个输入是否符合长度等对字段的判断。这样的代码可读性差,而且还不美观,那么使用Validation就可以完美解决这个问题。
2、使用Validation
- 引入validation依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 在需要校验的实体类添加注解
@Data
public class User {
private String id;
@NotNull(message = "姓名不能为空")
private String name;
}
- 在Controller类的方法入参增加@Valid
@PostMapping(path = "")
public RestResponse save(@Valid @RequestBody User user){
return ResponseFactory.getOkResponse();
}
- 使用全局异常处理异常信息
全局异常处理在上一篇文章有介绍到,具体怎么使用可以参考:SpringBoot全局异常处理
@ExceptionHandler(MethodArgumentNotValidException.class)
public RestResponse paramExceptionHandler(MethodArgumentNotValidException e) {
BindingResult bindingResult = e.getBindingResult();
if (bindingResult.hasErrors()) {
List<ObjectError> objectError = bindingResult.getAllErrors();
if (!objectError.isEmpty()) {
return ResponseFactory.getErrorMessage(objectError.stream().map(obj -> {
FieldError fieldError = (FieldError) obj;
return String.format("%s-%s", fieldError.getField(), fieldError.getDefaultMessage());
}).collect(Collectors.joining(";")));
}
}
return ResponseFactory.getErrorMessage("参数请求错误!");
}
3、测试
入参:
{
"id":"as",
"name":null
}
出参:
{
"code": "1",
"message": "name-姓名不能为空",
"data": null
}
从出参可以看出,验证已经生效。这里需要注意的是,如果实体类中嵌套了实体类,需要在嵌套的类上加@Valid
才会对嵌套的实体类校验。
@Data
public class User {
private String id;
@NotNull(message = "姓名不能为空")
private String name;
@NotNull(message = "地址信息不能为空!")
private Address address;
}
@Data
public class Address {
private String id;
@NotEmpty(message = "省份不能为空!")
private String province;
}
如上只是在address
上面加了非空校验,在Address
类中的province
添加了非空校验,如果不再address
加@Valid
,入参不传入address
信息,如下:
入参:
{
"id":"as",
"name":null
}
出参:
{
"code": "1",
"message": "name-姓名不能为空;address-地址信息不能为空!",
"data": null
}
入参加上address
的空信息,入参出参如下:
入参:
{
"id":"as",
"name":null,
"address":{
}
}
出参:
{
"code": "1",
"message": "name-姓名不能为空",
"data": null
}
可以看出在address
上不加@Valid
注解,对嵌套类的校验是不生效的,接下来@Valid
注解加上看下结果:
@Data
public class User {
private String id;
@NotNull(message = "姓名不能为空")
private String name;
@NotNull(message = "地址信息不能为空!")
@Valid
private Address address;
}
入参不变,出参如下:
{
"code": "1",
"message": "address.province-省份不能为空!;name-姓名不能为空",
"data": null
}
从结果可以看出,嵌套类中的校验已经生效。
上面的示例只用到了@NotNull
、@NotEmpty
注解,还有一些常用的注解,这里就不一一演示了,可以自己测试下。下面贴出一些常用校验注解:
注解 | 作用 |
---|---|
@NotNull | 值不能为空 |
@Null | 值必须为空 |
@Pattern(regex=) | 字符串必须匹配正则表达式 |
@Size(min, max) | 集合或者数组元素的数量必须在min和max之间 |
@CreditCardNumber(ignoreNonDigitCharacters=) | 字符串必须是信用卡号,按找美国的标准验证 |
字符串必须是Email地址 | |
@Length(min, max) | 检查字符串的长度 |
@NotBlank | 字符串不能为空串 |
@NotEmpty | 字符串不能为null, 集合或者数组的 size 不能为空 |
@Range(min, max) | 数字必须大于min, 小于max |
@SafeHtml | 字符串必须是安全的html |
@URL | 字符串必须是合法的URL |
@AssertFalse | 值必须是false |
@AssertTrue | 值必须是true |
@DecimalMax(value=, inclusive=) | 值必须小于等于(inclusive=true)/小于(inclusive=false)属性指定的值,也可以注释在字符串类型的属性上。 |
@DecimalMin(value=, inclusive=) | 值必须大于等于(inclusive=true)/小于(inclusive=false)属性指定的值,也可以注释在字符串类型的属性上。 |
@Digist(integer=,fraction=) | 数字格式检查。integer指定整数部分的最大长度,fraction指定小数部分的最大长度 |
@Future | 时间必须是未来的 |
@Past | 事件必须是过去的 |
@Max(value=) | 值必须小于等于value指定的值。不能注解在字符串类型属性上。 |
@Min(value=) | 值必须小于等于value指定的值。不能注解在字符串类型属性上。 |