一、Hibernate-Validator简介
在RESTful 风格的接口服务中,会有各种各样的入参,我们不可能完全不做任何校验就直接进入到业务处理的环节,因此在前期我们会有一个基础的数据验证的机制,待这些验证通过后,参数才会进入到正式的业务处理环节。
数据验证又分为两种:
(1)一种是无业务关联的规则性验证;
(2)一种是根据现有数据进行的联动性数据验证(简单来说,参数的合理性需要查数据库)。
Hibernate-Validator 是一种校验机制,比较适合做无业务关联的规则性验证。
官网:http://hibernate.org/validator/releases/6.0/
在使用时需要在pom中引入依赖,如下所示:
<!-- hibernate校验依赖 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.15.Final</version>
</dependency>
二、JSR 303和JSR 349
简单来说,就是Java规定了一套关于验证器的接口。开始的版本是Bean Validation 1.0(JSR-303),然后是Bean Validation 1.1(JSR-349),目前最新版本是Bean Validation 2.0(JSR-380),官网入口:https://beanvalidation.org/2.0/
从上可以看出Bean Validation并不是一项技术而是一种规范,需要对其实现。hibernate团队提供了参考实现,Hibernate validator 5是Bean Validation 1.1的实现,Hibernate Validator 6.0是Bean Validation 2.0规范的参考实现。新特性可以到官网查看。对于方法参数/返回值验证,大家可以参阅《hibernate官方文档) 》
如果项目的框架是spring boot的话,在依赖spring-boot-starter-web中已经包含了Hibernate-validator的依赖。Hibernate-Validator的主要使用的方式就是注解的形式,并且是“零配置”的,也就是说无需配置也可以使用。
三、Hibernate-Validator内置的校验注解
首先列举一下Hibernate-Validator所有的内置验证注解。
常用的校验注解如下表所示:
注解 | 说明 |
---|---|
@NotNull | 被注释的元素(任何元素)必须不为null,但集合为空也是可以的。没啥实际意义 |
@NotEmpty | 用来校验字符串、集合、map、数组不能为null或空 (字符串传入空格也不可以)(集合需至少包含一个元素)功能强于@NotNull |
@NotBlank | 只用来校验字符串不为null,不为空值,不为全空格。功能强大于@NotEmpty |
@Size(max=, min=) | 指定的字符串、集合、map、数组长度必须在指定的max和min范围内。(允许元素为null,字符串允许为空格) |
@Length(min=,max=) | 只用来校验字符串,长度必须在指定的max和min范围内。(允许元素为null) |
@Range(min=,max=) | 用来校验数字或字符串的大小必须在指定的min和max范围内,字符串会转成数字进行比较,如果不是数字校验不通过。(允许元素为null) |
@Min() | 校验数字(包括integer、short、long、int等)的最小值,不支持小数即double和float。(允许元素为null) |
@Max() | 校验数字(包括integer、short、long、int等)的最大值,不支持小数即double和float。(允许元素为null) |
@Pattern() | 正则表达式匹配,可用来校验年月日格式是否包含特殊字符 |
@Valid | 递归的对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验 |
主要区分下@NotNull、@NotEmpty、@NotBlank 3个注解的区别:
(1)@NotNull:任何对象的value不能为null。
(2)@NotEmpty:集合对象的元素不为0,即集合不为空,也可以用于字符串不为null。
(3)@NotBlank:只能用于字符串不为null,并且字符串trim()以后length要大于0。
需要注意如下几点:
(1)除了@Empty要求字符串不能全是空格,其他的字符串校验都是允许空格的。
(2)message是可以引用常量的,但是如@Size里max不允许引用对象常量,基本类型常量是可以的。message是错误提示信息,是可以返回给前台的。
(3)大部分规则校验都是允许参数为null,即当不存在这个值时,就不进行校验了。
不太常用的校验注解如下表所示:
注解 | 说明 |
---|---|
@Null | 被注释的元素必须为null |
@AssertTrue | 被注释的元素必须为true |
@AssertFalse | 被注释的元素必须为false |
@DecimalMin(value=,message=) | 被注释的元素必须是一个数字,其值必须大于等于指定的最小值 |
@DecimalMax(value=,message=) | 被注释的元素必须是一个数字,其值必须小于等于指定的最大值 |
@Digits (integer, fraction) | 被注释的元素必须是一个数字,其值必须在可接受的范围内 |
@Past | 被注释的元素必须是一个过去的日期 |
@Future | 被注释的元素必须是一个将来的日期 |
被注释的元素必须是电子邮箱地址 |
四、实际使用
使用Hibernate Validator做简单检验时,使用注解即可,需要引入Hibernate Validator包。只需要在bean写上具体校验注解,controller层入参加上@Validated注解,接口入参上加上@Validated注解即可。
如下所示:
@RequestMapping(value = "/addgoods")
public Results addGoods(@Validated @RequestBody GoodsAddDTO goodsAddDTO, BindingResult result) {
// 在校验过程中如果发生校验不成功的情况,则需要收集失败信息,以返回给用户
if (result.hasErrors()) {
return Results.error(-1, result.getFieldError().getDefaultMessage());
}
// 调用service层并返回结果
}
接口层如下:
Results savaGoods(@Valid GoodsAddDTO goodsAddDTO);
bean如下:
public class GmsGoodsBasicInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
@NotEmpty(message = "商品编号不能为空")
@Length(min = 1, max = 10, message = "商品编号长度在1到10之间")
private String goodsCode;
//setter/getter
}
参考博文:
(1)https://blog.csdn.net/java_collect/article/details/85534054
(2)https://blog.csdn.net/xgblog/article/details/52548659
(3)https://blog.csdn.net/danielzhou888/article/details/74740817
(4)https://www.jianshu.com/p/2c958b377dd2
(5) https://blog.csdn.net/ye___li/article/details/107512099 (复杂校验,list,嵌套对象校验等)
(6) https://blog.csdn.net/jinzhencs/article/details/51682830
(7) https://juejin.im/post/6844903929331843086 (基本用法,和返回校验出错结果,嵌套校验等)