Springboot使用validator进行参数校验
添加数据效验
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>6.0.15.Final</version></dependency>
单字段效验
- 添加效验注解
@DatapublicclassUsers{privateint id;@NotBlank(message="用户名不能为空")@Length(min=1, max=20, message="用户名长度需要在20个字以内")privateString name;@Pattern(regexp="^[1][3,4,5,6,7,8,9][0-9]{9}$", message="手机号格式有误")privateString phone;@Pattern(regexp="^[0-9]{4}-[0-9]{2}-[0-9]{2}$",message="出生日期格式不正确")privateString birthday;@Email(message="请输入正确的邮箱")privateString email;@Size(min=1, max=5)privateList<String> strings;}
- 其他常用的注解
注解 | 说明 |
---|---|
@Range(min=最小值, max=最大值) | 验证注解的元素值在最小值和最大值之间 |
@Min(value=值) | 验证注解的元素值大于等于@Min指定的value值 |
@Max(value=值) | 验证注解的元素值小于等于@Max指定的value值 |
@Past | 验证注解的元素值(日期类型)比当前时间早 |
@Future | 验证注解的元素值(日期类型)比当前时间晚 |
@AssertFalse | 可以为null,如果不为null的话必须为false |
@AssertTrue | 可以为null,如果不为null的话必须为true |
@Digits | 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内 |
级联效验
带校验的成员里存在级联对象时,也进行校验
@DatapublicclassUsers{@ValidprivateCollections collections;}
分组效验与组序列
分组效验:将实体类的属性进行分组,标记后,在进行效验时,可以指定分组进行效验
组序列:指定分组执行效验的顺序,Default.class为默认分组
/****新增时,需要效验的字段分组****/publicinterfaceAddGroup{}/****更新时,需要效验的字段分组****/publicinterfaceUpdateGroup{}@DatapublicclassCollections{@NotBlank(message="修改时,id不能为空!",groups=UpdateGroup.class)privateint id;@NotBlank(message="新增时,name不能为空!",groups=AddGroup.class)privateString name;@NotBlank(message="新增和修改时,userid都不能为空!",groups={AddGroup.class,UpdateGroup.class})privateint userId;privateString content;privateString remark;//组序列@GroupSequence({Default.class,AddGroup.class,UpdateGroup.class})publicinterfaceGroup{}}
多字段关联效验
场景描述:根据某个字段的值不同,对其他不同的属性进行效验
occupation字段为1时,说明该用户为学生,学校、入学时间、毕业时间为必填项
occupation字段为2时,说明该用户为在职员工,公司和职位为必填项
- 添加效验注解
@GroupSequenceProvider(UsersGroupSequenceProvider.class)@DatapublicclassUsers{privateint occupation;//职业:学生 1 / 职工 2@NotBlank(message="学校不能为空!",groups=StudentGroup.class)privateString school;//学校@NotNull(message="入学时间为必填项!",groups=StudentGroup.class)privateDate admissionTime;//入学时间@NotNull(message="毕业时间为必填项!",groups=StudentGroup.class)privateDate graduationTime;//毕业时间@NotNull(message="公司不能为空!",groups=WorkGroup.class)privateString company;//公司@NotNull(message="职位不能为空!",groups=WorkGroup.class)privateString position;//职位publicinterfaceStudentGroup{}publicinterfaceWorkGroup{}@GroupSequence({Default.class,StudentGroup.class,WorkGroup.class})publicinterfaceGroup{}}
- 自定义分组序列提供器
实现DefaultGroupSequenceProvider接口,根据当前对象实例的occupation值,动态来决定加载哪些校验组进入默认校验组。
publicclassUsersGroupSequenceProviderimplementsDefaultGroupSequenceProvider<Users>{@OverridepublicList<Class<?>>getValidationGroups(Users users){List<Class<?>> defaultGroupSequence=newArrayList<>();
defaultGroupSequence.add(Users.class);if(users!=null){int occupation= users.getOccupation();if(occupation==1){//为学生时,效验StudentGroup分组的字段
defaultGroupSequence.add(Users.StudentGroup.class);}else{//为在职员工时,效验WorkGroup分组的字段
defaultGroupSequence.add(Users.WorkGroup.class);}}return defaultGroupSequence;}}
执行数据效验
/**
* 统一结果类
*/@DatapublicclassResultCode{privateInteger code;privateString msg;publicResultCode(Integer code,String msg){this.code= code;this.msg= msg;}}
@Valid注解
处理validator异常
validator进行参数效验时,未通过效验会抛出MethodArgumentNotValidException异常,捕获并封装为统一结果类返回给前端。
@RestControllerAdvicepublicclassResultExceptionHandler{@ExceptionHandler(MethodArgumentNotValidException.class)publicResultCodehandleMethodArgumentNotValidException(MethodArgumentNotValidException e){Map<String,String> errors=newHashMap<>();
e.getBindingResult().getAllErrors().forEach((error)->{
errors.put(((FieldError)error).getField(),error.getDefaultMessage());});returnnewResultCode(500,errors.values().toString());}}
controller接口处理
使用@Valid注解进行参数效验,不指定具体分组
@RestController@RequestMapping("/users")publicclassUsersController{@PostMapping("checkUsers")publicResultCodecheckUsers(@RequestBody@ValidUsers user){//usersService.save(user);returnResultCode.success();}}
ValidatorUtils工具类
自定义异常及处理
自定义参数效验异常:ParamException
publicclassParamExceptionextendsRuntimeException{privateint code=500;privateString msg;publicParamException(){super();}publicParamException(String msg){super(msg);this.msg= msg;}publicParamException(int code,String msg){super(msg);this.msg= msg;this.code= code;}publicParamException(String msg,Throwable cause){super(msg, cause);this.msg= msg;}publicintgetCode(){return code;}publicStringgetMsg(){return msg;}}
捕获自定义ParamException异常并封装为统一结果类返回给前端。
@RestControllerAdvicepublicclassResultExceptionHandler{@ExceptionHandler(ParamException.class)publicResultCodehandleParamException(ParamException e){returnnewResultCode(e.getCode(),e.getMsg());}}
ValidatorUtils与接口
ValidatorUtils工具类,可以指定分组,或,只执行默认分组的效验
publicclassValidatorUtils{privatestaticValidator validator;static{
validator=Validation.buildDefaultValidatorFactory().getValidator();}/**
* 校验对象
* @param object 待校验对象
* @throws ParamException 校验不通过,则报ParamException异常
*/publicstaticvoidvalidateEntity(Object object)throwsParamException{Set<ConstraintViolation<Object>> constraintViolations= validator.validate(object,Default.class);if(!constraintViolations.isEmpty()){ConstraintViolation<Object> constraint= constraintViolations.iterator().next();thrownewParamException(constraint.getMessage());}}/**
* 分组校验对象
* @param object 待校验对象
* @param groups 待校验的组
* @throws ParamException 校验不通过,则报ParamException异常
*/publicstaticvoidvalidateEntity(Object object,Class<?>... groups)throwsParamException{Set<ConstraintViolation<Object>> constraintViolations= validator.validate(object, groups);if(!constraintViolations.isEmpty()){ConstraintViolation<Object> constraint= constraintViolations.iterator().next();thrownewParamException(constraint.getMessageTemplate());}}}
controller接口调用ValidatorUtils方法进行效验,并传参分组
@PostMapping("checkUsersByGroup")publicResultCodecheckUsersByGroup(@RequestBodyUsers user){ValidatorUtils.validateEntity(user,Users.Group.class);//usersService.save(user);returnResultCode.success();}