一、参数校验
用于参数校验的注解如下:
注解 | 功能 |
@AssertTrue | 所注解的元素必须是Boolean类型,且值为true |
@AssertFalse | 所注解的元素必须是Boolean类型,且值为false |
@Max(value = ) | 所注解的元素必须是数字,且值不呢个大于等于给定的值(最大值) |
@Min(value = ) | 所注解的元素必须是数字,且值不能小于等于给定的值(最小值) |
@DecimalMax( value ) | 所注解的元素必须是数字,且值小于等于给定的值 |
@DecimalMin( value ) | 所注解的元素必须是数字,且值大于等于给定的值 |
@Digits | 所注解的元素必须是数字,且值必须是指定的位数 |
@Future | 所注解的元素必须是将来某个日期 |
@Range | 所注解的元素需在指定范围区间内 |
@NotBlank | 所注解的元素值有内容 |
@Null | 所注解的元素值必须为 null |
@NotNull | 所注解的元素值不能为null,注意:如果id为 "" 空字符串,校验会通过! 需要使用 @NotEmpty |
@NotEmpty | 所注解的元素值不能为null 和 不能为 "" 空字符串。 |
@Past | 所注解的元素必须是某个过去的日期 |
@PastOrPresent | 所注解的元素必须是过去某个或现在日期 |
@Pattern (regex = , flag = ) | 所注解的元素必须满足给定的正则表达式 |
@Size( min= , max= ) | 所注解的元素必须是String、集合或数组,且长度大小需保证在给定范围之内 |
所注解的元素需满足Email格式 |
提示:
以上注解只要是参数必须为数字的不能用在get请求上,因为get请求所有的参数都是拼接到路径上的,后端拿到的都是字符串,否则会出现类似如下异常:
第一步:添加依赖
<!--校验依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
第二步:添加校验规则
public class User {
private Integer id;
@NotNull(message = "name不能为空")
private String name;
@Max(value=2, message = "年龄不能超过2位数")
private Integer age;
private String account;
private String password;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
第三步:开启校验规则
@Valid User user 表示这一组参数要开启校验。
// 插入/添加 数据
@PostMapping(value = "/updataOrAddUser")
public ComResponse updataOrAddUser(@RequestBody @Valid User user) {
return userService.updataOrAddUserService(user);
}
第四步:编写统一的异常处理类
异常处理,这篇文章记录!
单个参数校验
如果方法只有一个参数,也可以把 校验的注解放在参数前,但是要注意,这种方式还需要 把@Validted添加到类上:
@RestController
@Validated
public class TestController {
// 根据id删除数据
@GetMapping(value = "/deleteById/{id}")
public ComResponse deleteById(@PathVariable @Min(value= 1, message = "id必须大于等于1") int id) {
return userService.deleteById(id);
}
}
有个问题,这种方式定义的全局异常类捕获不到,不知道为啥,晚上在测试下!
补充:
单个参数校验抛出的异常为:ConstraintViolationException。
全局异常类:
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public Map<String, Object> paramValidate(ConstraintViolationException mne) {
String msg = mne.getMessage();
HashMap mapList = new HashMap<>();
mapList.put("errors:", msg);
return mapList;
}
测试:
@GetMapping(value = "/deleteById/{id}")
public String deleteById (@PathVariable @Min(value=10, message = "id最小值为10") int id) {
System.out.println("id:"+id);
return "删除成功";
}
二、@Valid 和 @Validated
这两个的区别,很简单,看源码就知道了。
@Valid
(1)只能用在方法、字段属性(枚举常量)、类构造方法、参数上,最后一个 TYPE_USER 不认识。
(2)没有属性。
@Validated
(1)只能用在 类、接口、枚举、自定义的注解、方法、参数上;
(2)有属性,且只有一个属性 value,有默认值, 所以使用它的使用value 可以省略,@Validated( { xx.class, xxx.class, ··· ··· } ) , 也可以只写一个@Validated, 值是一个数组,里边的元素类型必须是 Class类型的。
三、分组校验
实际开发中,添加数据时,前端不会传id,id通常是后端生成的;但是修改数据id是必须传的,如果在实体类的id上直接添加 @NotNull(), 很显然无法实现这样的需求。此时可以定义分组,在需要校验id的时候校验,不需要校验的时候不校验。
第一步:定义空接口,来表示一个组别
// 分组A
package com.lxc.springboot.emptyInterface;
// 作为分组用
public interface GroupAInterface {}
// 分组B
package com.lxc.springboot.emptyInterface;
public interface GroupBInterface {}
第二步:实体类中,给id添加组
public class User {
// 定义一个组 GroupAInterface
@NotNull(message = "id 不能为空", groups = {GroupAInterface.class})
private Integer id;
// 也可以定义多个分组
@NotNull(message = "name不能为空", groups = {GroupAInterface.class, GroupBInterface.class})
public String name;
}
第三步:在controller层,需要验证id的 方法参数前定义这个组,即可。
// 编辑 (编辑时,id必须要验证,name也需要校验)
@PostMapping(value = "/updateUser")
public ComResponse updateUser(@RequestBody @Validated(value = {GroupAInterface.class, GroupBInterface.class}) User user) {
return userService.updataOrAddUserService(user);
}
// 添加 (添加时,id不需要验证, name需要校验)
@PostMapping(value = "/addUser")
public ComResponse AddUser(@RequestBody @Validated(value = {GroupBInterface.class}) User user) {
return userService.updataOrAddUserService(user);
}