SpringBoot 的请求参数校验注解
Validation 和 validator 包提供了一系列校验用注解,帮助我们在 RESTful 服务请求中实现期望的数据校验,其注解的功能包括但不限于入参的存在性判断、非空判断、数值取值范围限定、特定含义数据格式校验、校验失败提示信息等。
Maven 依赖
在 SpringBoot 2.3 版本之前的项目中,主要需要添加的依赖包括以下两个。其中 spring-boot-starter-web
包含了 spring-boot-starter-validation
这个 maven 包,而里面则添加了 javax-validation
和 hibernate-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类型;可以通过指定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 的请求参数校验注解相关推荐
- Springboot中请求参数校验
1.添加依赖 <!-- 参数校验 --> <dependency><groupId>org.springframework.boot</groupId> ...
- Spring Boot 2.x基础教程:JSR-303实现请求参数校验
点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! 作者 | 翟永超 来源 | didispace.com/spring-boot-learni ...
- struts2教程(5)--请求参数校验
一.请求参数校验介绍 校验的分类 :客户端数据校验 和服务器端数据校验 客户端数据校验 ,通过JavaScript完成校验 (改善用户体验,使用户减少出错 ) 服务器数据校验 ,使用框架内置校验功能( ...
- SpringBoot 如何进行参数校验,老鸟们都这么玩的!
大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...
- 解决Springboot GET请求参数过长的情况
项目场景: 使用Spring Boot进行项目开发,解决Springboot GET请求参数过长的情况 问题描述 报错信息:Springboot GET请求参数过长抛出异常:Request heade ...
- SpringBoot全局异常处理及前端请求参数校验
SpringBoot全局异常捕获处理及参数校验 文章目录 SpringBoot全局异常捕获处理及参数校验 为什么要用全局异常处理? 如何进行全局异常捕获和处理? 统一结果封装 统一返回结果 枚举类 使 ...
- e0312 不存在用户定义的_更加灵活的参数校验,Spring-boot自定义参数校验注解
上文我们讨论了如何使用@Min.@Max等注解进行参数校验,主要是针对基本数据类型和级联对象进行参数校验的演示,但是在实际中我们往往需要更为复杂的校验规则,比如注册用户的密码和确认密码进行校验,这个时 ...
- boot spring 对参数检测_【springboot】@Valid参数校验
转自: https://blog.csdn.net/cp026la/article/details/86495659 扯淡: 刚开始写代码的时候对参数的校验要么不做.要么写很多类似 if( xx == ...
- springboot 优雅的参数校验_SpringBoot 2.x 开发案例之优雅的校验参数
前言 参数如何校验?撸主很久很久之前的项目都是在前端页面一个个 if else 的,后来就用了一系列的前端校验框架,比如 layui iview 等等,几个样式属性就可以轻松搞定,的确是美滋滋. 后端 ...
- SpringBoot 实现统一参数校验
一.业务需求 与第三方平台对接,第三方调用接口实现数据上报.由于接口传参较多,要对每一个参数做校验,如果写工具类对每个参数校验会很麻烦,因为,使用springboot自带的校验功能实现对参数的统一校验 ...
最新文章
- python 树状图可视化_Python可视化25|seaborn矩阵图
- 如何打印CloudFoundry上应用运行时的环境变量
- java 中获取file的长度为0_Java核心技术梳理-IO
- Windows批处理文件(.bat文件和.cmd文件)简单使用
- 同步请求和异步请求的区别
- aix 查看内存,CPU 配置信息
- 《深入浅出MFC》 第二版中文
- 血汗泪计算机音乐,血汗泪 - pikaCinDy_ - 5SING中国原创音乐基地
- [安全攻防进阶篇] 八.那些年的熊猫烧香及PE病毒行为机理分析
- 路侧智慧泊车解决方案
- 决策树后剪枝算法(二)错误率降低剪枝REP
- 做市商策略(Market Making Strategy)
- 静态路由,缺省路由和默认网关的区别
- 【Mysql】Mysql数据库查询“表空间”
- List 常用的 Lambda 操作
- Python吴恩达深度学习作业16 -- 人脸识别
- html怎么设置字体于字体的间隔,如何在css中设置字体间隔
- 设计模式第一篇——简单工厂模式&类图
- Excel Charting Utility赠品
- 潍坊职业学院计算机应用技术代码,潍坊职业学院计算机应用(软件外包)专业开展“日语书法比赛”活动...