spring Validated是基于java JSR303进一步封装,具有校验功能的框架,封装了原本的@Valid,但不同于@Valid的是他具有分组功能

依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency>

代码

数据校验需要在两个位置用到spring Validated的注解,一个是在请求参数的位置,一个是在实体类的位置。

请求参数:

参数需要使用@Validated注解标注,表示该参数需要被校验

  @GetMapping("/getAll")public UserVo getAll(@Validated UserVo userVo) {return userVo;}

实体类:

在属性位置标注上对应的注解比如 @NotEmpty(message = “用户名不为空”),表示name不能为空,为空白字符,长度不能为0

@Data
public class UserVo {@NotEmpty(message = "用户名不为空")private String name;@Min(value = 18,message = "年龄必须大于18岁")private String age;@Email(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$",message = "邮箱格式错误")private String email;
}

那如果我们需要对某些字段进行校验,或者按照某种条件进行校验,我们该怎么做呢?
那么我们就需要分组校验来进行
下面我们进行分组校验测试

分组校验

分组接口

先创建两个接口,这两个接口不需要任何内容,就只是用于分组标记

public interface IGroupA {}
public interface IGroupB {}

请求参数

我们在请求参数出设置校验标记,
@Validated({IGroupB.class})表示只有分组为IGroupB.class才进行校验,否则不校验

    @GetMapping("/getAll")public UserVo getAll(@Validated({IGroupB.class}) UserVo userVo) {return userVo;}

实体类:

groups = IGroupB.class表示将这个校验标记为IGroupB分组,如果controller不是IGroupB就不进行校验。否则就校验

@Data
public class UserVo {@NotEmpty(message = "用户名不为空", groups = IGroupA.class)private String name;//只有分组为IGroupB才进行校验@NotBlank@Min(value = 18, message = "年龄必须大于18岁", groups = {IGroupB.class})private String age;@NotBlank@Email(message = "邮箱格式错误", groups = {IGroupB.class})private String email;
}

如果访问,上面的结果是:name不会校验,age和email会进行校验。

那如果在请求参数处同时标记IGroupA.class,IGroupB.class会怎么样呢?

 @GetMapping("/getAll")public UserVo getAll(@Validated({IGroupA.class,IGroupB.class}) UserVo userVo) {return userVo;}

答案就是:三个都会进行校验,那如果我们对一个进行校验后发现不通过,后面的就不需要进行校验该怎么办呢?
那么我们可以采用组序列,在使用组序列验证的时候,如果序列前边的组验证失败,则后面的组将不再给予验证。

组序列

创建一个接口:IGroup

在上面标注注解,@GroupSequence({Default.class, IGroupA.class, IGroupB.class})

import javax.validation.GroupSequence;
import javax.validation.groups.Default;@GroupSequence({Default.class, IGroupA.class, IGroupB.class})
public interface IGroup {}

实体类

对实体类的属性上同时标注上groups = IGroupB.class和groups = IGroupA.class)

@Data
public class UserVo {@NotEmpty(message = "用户名不为空", groups = IGroupA.class)private String name;//只有分组为IGroupB才进行校验@Min(value = 18, message = "年龄必须大于18岁", groups = {IGroupB.class})private String age;@Email(message = "邮箱格式错误", groups = {IGroupB.class})private String email;
}

请求参数

在请求参数处标注一个@Validated({IGroup.class})注解

 GetMapping("/getAll")public UserVo getAll(@Validated({IGroup.class}) UserVo userVo) {return userVo;}

再进行测试;
如果我们三个参数都填错,那么按照顺序,他只会校验name后就不再进行校验。
那如果我们实体类中是以另一个实体类为属性,我们能对他进行校验吗?
那当然可以。

嵌套校验

创建另一个实体类Teacher

import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
@Data
public class Teacher {@NotEmpty(message = "老师姓名不能为空")private String teacherName;@Min(value = 1, message = "至少为1")private int type;
}

实体类

将其封装到UserVo中

@Data
public class UserVo {@NotEmpty(message = "用户名不为空", groups = IGroupA.class)private String name;//只有分组为IGroupB才进行校验@Min(value = 18, message = "年龄必须大于18岁", groups = IGroupB.class)private String age;@Email(message = "邮箱格式错误", groups = IGroupB.class)private String email;@NotNull(message = "用户不能为空")@Size(min = 1,message = "至少有一个用户")private List<Teacher>  teachers;
}

请求参数

我们访问前端接口测试

@GetMapping("/getAll")public UserVo getAll(@Validated({IGroup.class}) UserVo userVo) {return userVo;}

参数为:

发现只校验了NotNull, 和 Size,并没有对teacher信息里面的字段进行校验,因为我们type给的0,那么应该校验发出校验,
这里teacher中的type明显是不符合约束要求的,但是能检测通过,是因为在student中并没有做 嵌套校验

解决办法

可以在teacherBeans中加上 @Valid,

@Data
public class UserVo {@NotEmpty(message = "用户名不为空", groups = IGroupA.class)private String name;//只有分组为IGroupB才进行校验@Min(value = 18, message = "年龄必须大于18岁", groups = IGroupB.class)private String age;@Email(message = "邮箱格式错误", groups = IGroupB.class)private String email;@Valid@NotNull(message = "用户不能为空")@Size(min = 1,message = "至少有一个用户")private List<Teacher>  teachers;
}

我们再次测试
发现结果对teacher类中的字段进行了校验。测试成功

将@Validated的返回信息通过全局异常类同意处理

先创建一个全局异常类

/*** 统一异常处理*/
@RestControllerAdvice
public class GlobalExceptionHandler {/*** jsr303校验异常* @param e* @return*/@ExceptionHandler({MethodArgumentNotValidException.class})public R validatedException(MethodArgumentNotValidException e){BindingResult bindingResult = e.getBindingResult();String field = bindingResult.getFieldError().getField();if("mobile".equals(field)){return R.error().code("30").message(bindingResult.getFieldError().getDefaultMessage());}else{return R.error().code("31").message(bindingResult.getFieldError().getDefaultMessage());}}
}

参数vo实例类

@Data
public class RegisterVo implements Serializable {//手机号@NotBlank(message = "手机号码不能为空")@Pattern(regexp = "^[1][3,4,5,7,8,9][0-9]{9}$",message = "手机号码不正确")private String mobile;//密码@NotBlank(message = "密码不能为空")private String password;//@NotBlank校验字符不为null,不为空字符串(" "),字符长度不为0("")//@NotEmpty校验字符不为null,字符长度不为0("")@NotBlank(message = "昵称不能为空")private String nickname;
}
    @PostMapping("register")public R register(@RequestBody @Validated RegisterVo registerVo){memberService.register(registerVo);return R.ok().message("注册成功");}

可用注解说明

@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格式

springboot整合spring Validated相关推荐

  1. 八、springboot整合Spring Security

    springboot整合Spring Security 简介 Spring Security是一个功能强大且可高度自定义的身份验证和访问控制框架.它是保护基于Spring的应用程序的事实标准. Spr ...

  2. springboot整合spring @Cache和Redis

    转载自  springboot整合spring @Cache和Redis spring基于注解的缓存 对于缓存声明,spring的缓存提供了一组java注解: @Cacheable:触发缓存写入. @ ...

  3. SpringBoot整合Spring Data Elasticsearch

    特点: 分布式,无需人工搭建集群(solr就需要人为配置,使用Zookeeper作为注册中心) Restful风格,一切API都遵循Rest原则,容易上手 近实时搜索,数据更新在Elasticsear ...

  4. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离

    在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与权限管理. ...

  5. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  6. SpringBoot 整合 Spring Security 实现安全认证【SpringBoot系列9】

    SpringCloud 大型系列课程正在制作中,欢迎大家关注与提意见. 程序员每天的CV 与 板砖,也要知其所以然,本系列课程可以帮助初学者学习 SpringBooot 项目开发 与 SpringCl ...

  7. SpringBoot整合Spring Security【超详细教程】

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/Lee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 Spring Security是一个 ...

  8. springboot整合spring Cache(redis)

    前言 前面有介绍过spring整合redis和redis的一些注意点,在实际开发中,spring cache方便简化的缓存操作的大部分内容.通过注解的方式实现缓存. 阅读前推荐先阅读:redis缓存介 ...

  9. 第九章SpringBoot整合Spring Data JPA

    目录 1 概述 2 Spring Data JPA整合 2.1 pom文件 2.2 配置文件 2.3 实体类 2.4 Dao接口 2.5 启动类 2.6 编写测试类 3 Spring Data JPA ...

最新文章

  1. poj1679(次小生成树)
  2. php抓取运动步数,使用PHP抓取微博数据
  3. 高级Java泛型:检索泛型类型参数
  4. ONGC的完整形式是什么?
  5. 英文.数字和中文混合的彩色验证码【JSP】
  6. eclipse工程运行正常但是工程有红叉的问题
  7. (转)对各种初始化函数的理解:OnInitDialog、InitInstance、InitApplication函数的理解...
  8. OpenCV访问像素的三种方法
  9. NOSQL数据库习题
  10. 在python中安装插件pynput实现聊天窗口消息轰炸
  11. mysql和oracle的字符串拼接_Oracle和Mysql中的字符串的拼接
  12. GPC凝胶色谱理论和应用(一)
  13. 首月流水2.39亿美元,《原神》的发行策略是什么?
  14. HTB TIER 2 Archetype wp
  15. mediasoup 管道通信类UnixStreamSocket分析
  16. 平板用电容笔还是触控笔?双十一值得买电容笔推荐
  17. 计算机领域顶级期刊是什么,喜报 | 我所一篇论文被计算机领域顶级期刊TKDE录用...
  18. 用vue实现类ant Design的日历组件
  19. Linux学习:第一天_笔记
  20. 2020应届毕业生,Android春招总结,已入职小米,进阶加薪全靠它

热门文章

  1. 完全解耦之模块化宅女作息策略:快速响应
  2. HRBUST 1161 树状数组区间更新求和
  3. Android移动应用开发——实验七——小鸭子报数(广播)
  4. 【VOLTE】关于VOLTE容量
  5. 四种JAD生成器之比较(附生成器下载)
  6. DCRAW TUTORIAL(dcraw指南)
  7. 车载开发之 CarLife
  8. 让自己的app出现在某类格式文件的默认打开列表中
  9. visual paradigm 时序图实用技巧
  10. 和真正的程序员在一起是怎样的体验【转载】