Validation 和 validator 包提供了一系列校验用注解,帮助我们在 RESTful 服务请求中实现期望的数据校验,其注解的功能包括但不限于入参的存在性判断、非空判断、数值取值范围限定、特定含义数据格式校验、校验失败提示信息等。

Maven 依赖

在 SpringBoot 2.3 版本之前的项目中,主要需要添加的依赖包括以下两个。其中 spring-boot-starter-web 包含了 spring-boot-starter-validation 这个 maven 包,而里面则添加了 javax-validationhibernate-validator 两个包含检验注解的依赖包。

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

而在 SpringBoot 2.3 之后的版本则需要单独引入 spring-boot-starter-validation 这个 maven 包。

常用注解说明

Maven 包:javax.validation.constraints:validation-api-2.0.1.Final

注解 作用数据类型 说明
@Null 任何类型 对象必须为空
@NotNull 任何类型 对象不为空
@NotBlank 字符串 对象不为空,字符串去掉前后空格后长度不为0
@NotEmpty 字符串、集合、数组 对象不为空,且字符串长度不为0,集合、数组大小不为0
@AssertTrue 布尔型 必须为true;null值有效,Boolean通过校验,boolean不可
@AssertFalse 布尔型 必须为false;null 可通过校验
@Min(number) 整型数 数值必须大于或等于指定的最小值
@Max(number) 整型数 数值必须小于或等于指定的最大值
@DecimalMin(decimal) 浮点型 数值必须大于或等于指定的最小值,内部使用BigDecimal定义数值对象;为 null 是校验通过;默认包含边界值
@DecimalMax(decimal) 浮点型 数值必须小于或等于指定的最大值,内部使用BigDecimal定义数值对象;为 null 是校验通过;默认包含边界值
@Positive 整型数 数值必须为正整数
@PositiveOrZero 整型数 数值必须为正整数或0
@Negative 整型数 数值必须为负整数
@NegativeOrZero 整型数 数值必须为负整数或0
@Digits 数值型或者字符串 作为数值其构成必须合法
@Digits(integer=, fraction=) 数值型 数值必须符合指定的整数精度和小数精度
@Size(min=, max=) 字符串、集合、数组 对象的大小在指定区间内;为 null 是校验通过
@Past Date或者Calendar对象 必须是一个过去的日期
@PastOrPresent Date或者Calendar对象 必须是一个过去或者当前的日期
@Future Date或者Calendar对象 必须是一个将来的日期
@FutureOrPresent Date或者Calendar对象 必须是一个将来或者当前的日期
@Pattern 字符串 必须是规则正确的正则表达式
@Email 字符串 必须是Email类型;可以通过指定regexp和flags来自定义email格式;为null时算作通过验证

关于 @AssertTrue 与 @AssertFalse 注解对 null 的校验说明,需要区分基本类型(boolean)与装箱类型(Boolean)两种情况。参数为null,校验时则将参数看作其数据类型对应的默认值。boolean 型的默认值为 false,因此 @AssertTure 验证失败;Boolean 型则仍为 null,根据 javadoc 的说明 “null elements are considered valid”,因此都认为是校验通过。

javax.validation.constraints 包仅仅定义了上面的一系列注解,真正的实现逻辑在 org.hibernate.validator 包中,在 SpringBoot 项目启动时一般都会自动引入 hibernate 包。

Maven 包:org.hibernate.validator.constraints:hibernate-validator-6.0.18.Final

注解 作用数据类型 说明
@Length(min=, max=) 字符串 字符串的长度在指定区间内
@Range(min=, max=) 数值型 数值必须在指定闭区间内
@CreditCardNumber 字符串 必须是通过Luhn校验和测试的信用卡号码
@URL 字符串 必须是URL地址
@UniqueElements 集合类 校验集合中的值都是唯一的,null 视为有效成员

@Validated实现字段分组校验

在请求参数中添加了上述注解后,还需要在接口接收的参数前加上 @Validated 注解,这些校验的注解才会生效,不加的话则是无效的。

在 controller 接口被调用时,上述注解对应的入参将会进行校验,但这种校验一旦接口被调用则是必须执行的,而不能根据调用调用业务的不同而进行分组处理。例如,在执行添加操作时,一般是多个参数都要求非空,个别参数需要满足其含义的约束;而在执行删除操作时,通常只需要一个起标识作用的 id 或者 seq 非空,其他参数一般都可以为空。为了以一种比较友好的代码逻辑实现这种需求,这里就可以引入分组校验的功能。

首先,可以根据业务的需要定义一些分组接口:

public abstract interface InsertGroup {}
public abstract interface UpdateGroup {}
public abstract interface DeleteGroup {}

然后,在参数使用注解校验的地方加入响应的分组,说明只有采用指定分组时,才会对参数进行校验:

@NotBlank(message="seq不能为空", groups = {DeleteGroup.class})
private String seq;@NotBlank(message="seq不能为空", groups = {DeleteGroup.class})
@Length(message="标题长度要求在{min}和{max}之间", min = 5, max = 20, groups = {InsertGroup.class, UpdateGroup.class})
private String title;

最后,在 controller 接口的请求参数中通过 @Validated 指定校验使用的分组:

@PostMapping("/add")
public Response add(@RequestBody @Validated({InsertGroup.class}) Request req) {return new Response.success();
}@PostMapping("/update")
public Response update(@RequestBody @Validated({UpdateGroup.class}) Request req) {return new Response.success();
}@PostMapping("/delete")
public Response delete(@RequestBody @Validated({DeleteGroup.class}) Request req) {return new Response.success();
}

@Valid

@Valid 注解自 Spring 中就开始使用,我们常常用它进行方法级别或者成员属性级别的校验。与 @Validated 相比,它常用于触发嵌套属性的验证,而不支持分组验证。这里的嵌套属性,指的是在请求体内部,将 @Valid 注解使用在一个类对象上,以触发对这个对象内部每一个嵌套属性的注解校验。举个例子:

public class ApplyForm {// ...@Valid@NotNullprivate PersonalInfo personalInfo;// ...
}

自定义校验注解

参照 @NullBlank 注解,定义了一个如下的自定义注解:

@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(DemoLength.List.class)
@Constraint(validateBy = {DemoLengthValidator.class})
public @interface DemoLength {long min() default 1;long max() default 10;String message() default "DemoLength validator annotation.";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};@Documented@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})@Retention(RetentionPolicy.RUNTIME)public @interface List {DemoLength[] value();}
}
  • 这是一个用于校验参数长度的检验注解,其可指定长度最小值、最大值、以及提示信息
  • @Constraint(validateBy = {DemoLengthValidator.class}) 指定自定义的注解校验类
public class DemoLengthValidator implements ConstraintValidator<DemoLength, Object> {private long min;private long max;@Overridepublic void initialize(DemoLength constraintAnnotation) {this.min = constraintAnnotation.min();this.max = constraintAnnotation.max();}@Overridepublic boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {if (o == null) {return true;}if (o instanceof String) {int length ((String) o).length();return min <= length && length <= max;} else if (o instanceof Integer || o instanceof Long) {long val = ((Number) o).longValue();return min <= length && length <= max;}return false;}
}

注解校验类实现了 ConstraintValidator 接口,接口需要指定注解类以及注解应用的参数类型,这里的 DemoLength 注解即可用于判断字符串长度,也可用于判断数值大小,因此参数类型可以指定为 Object。实现接口主要是为了实现两个方法,顾名思义,initialize 用于初始化注解的配置信息,isValid 则是具体的校验判断逻辑,其中这里将 null 视为有效参数。

注解的校验逻辑

之所以在 Controller 层的请求体参数使用校验注解即能完成校验,是因为 Spring 启动时会为 Controller 类添加一个拦截器 MethodValidationInterceptor,每当有请求进来的时候,拦截器会对亲求进行拦截,然后判断请求体或者方法是否带有 @Valid 或者 @Validated 注解。如果存在,那么请求会被 AOP 拦截且执行参数校验:校验通过,则可以继续执行后续的业务逻辑;校验不通过,则抛出 ConstraintViolationException 异常,携带配置的特定提示信息返回给请求方。具体源码可见 MethodValidationInterceptor 类。

SpringBoot 的请求参数校验注解相关推荐

  1. Springboot中请求参数校验

    1.添加依赖 <!-- 参数校验 --> <dependency><groupId>org.springframework.boot</groupId> ...

  2. Spring Boot 2.x基础教程:JSR-303实现请求参数校验

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | didispace.com/spring-boot-learni ...

  3. struts2教程(5)--请求参数校验

    一.请求参数校验介绍 校验的分类 :客户端数据校验 和服务器端数据校验 客户端数据校验 ,通过JavaScript完成校验 (改善用户体验,使用户减少出错 ) 服务器数据校验 ,使用框架内置校验功能( ...

  4. SpringBoot 如何进行参数校验,老鸟们都这么玩的!

    大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...

  5. 解决Springboot GET请求参数过长的情况

    项目场景: 使用Spring Boot进行项目开发,解决Springboot GET请求参数过长的情况 问题描述 报错信息:Springboot GET请求参数过长抛出异常:Request heade ...

  6. SpringBoot全局异常处理及前端请求参数校验

    SpringBoot全局异常捕获处理及参数校验 文章目录 SpringBoot全局异常捕获处理及参数校验 为什么要用全局异常处理? 如何进行全局异常捕获和处理? 统一结果封装 统一返回结果 枚举类 使 ...

  7. e0312 不存在用户定义的_更加灵活的参数校验,Spring-boot自定义参数校验注解

    上文我们讨论了如何使用@Min.@Max等注解进行参数校验,主要是针对基本数据类型和级联对象进行参数校验的演示,但是在实际中我们往往需要更为复杂的校验规则,比如注册用户的密码和确认密码进行校验,这个时 ...

  8. boot spring 对参数检测_【springboot】@Valid参数校验

    转自: https://blog.csdn.net/cp026la/article/details/86495659 扯淡: 刚开始写代码的时候对参数的校验要么不做.要么写很多类似 if( xx == ...

  9. springboot 优雅的参数校验_SpringBoot 2.x 开发案例之优雅的校验参数

    前言 参数如何校验?撸主很久很久之前的项目都是在前端页面一个个 if else 的,后来就用了一系列的前端校验框架,比如 layui iview 等等,几个样式属性就可以轻松搞定,的确是美滋滋. 后端 ...

  10. SpringBoot 实现统一参数校验

    一.业务需求 与第三方平台对接,第三方调用接口实现数据上报.由于接口传参较多,要对每一个参数做校验,如果写工具类对每个参数校验会很麻烦,因为,使用springboot自带的校验功能实现对参数的统一校验 ...

最新文章

  1. python 树状图可视化_Python可视化25|seaborn矩阵图
  2. 如何打印CloudFoundry上应用运行时的环境变量
  3. java 中获取file的长度为0_Java核心技术梳理-IO
  4. Windows批处理文件(.bat文件和.cmd文件)简单使用
  5. 同步请求和异步请求的区别
  6. aix 查看内存,CPU 配置信息
  7. 《深入浅出MFC》 第二版中文
  8. 血汗泪计算机音乐,血汗泪 - pikaCinDy_ - 5SING中国原创音乐基地
  9. [安全攻防进阶篇] 八.那些年的熊猫烧香及PE病毒行为机理分析
  10. 路侧智慧泊车解决方案
  11. 决策树后剪枝算法(二)错误率降低剪枝REP
  12. 做市商策略(Market Making Strategy)
  13. 静态路由,缺省路由和默认网关的区别
  14. 【Mysql】Mysql数据库查询“表空间”
  15. List 常用的 Lambda 操作
  16. Python吴恩达深度学习作业16 -- 人脸识别
  17. html怎么设置字体于字体的间隔,如何在css中设置字体间隔
  18. 设计模式第一篇——简单工厂模式&类图
  19. Excel Charting Utility赠品
  20. 潍坊职业学院计算机应用技术代码,潍坊职业学院计算机应用(软件外包)专业开展“日语书法比赛”活动...

热门文章

  1. Unity3D架构设计NavMesh寻路
  2. Xcode6使用iOS7模拟器调试的方法
  3. 4个入口8条光缆!我们这样与世界连接
  4. 【转载】测试金字塔实战
  5. Anomaly Detection with Partially Observed Anomalies译文
  6. html5分镜头脚本范例,分镜头脚本模板(小故事分镜头脚本范例)
  7. 基于mvc设计模式下的商品管理平台
  8. 银河帝国----基地边缘
  9. 未缓存的IPv6路由项链表
  10. 如何修改Linux开启进度条的图片