Spring Boot之——整合hibernate-validate

校验框架

1.1 校验框架入门

1.1.1 表单校验的重要性

  • 表单校验保障了数据有效性、安全性

image-20200505144306747

数据可以随意输入,导致错误的结果。后端表单校验的重要性。

1.1.2 表单校验分类

  • 校验位置:
    • 客户端校验
    • 服务端校验
  • 校验内容与对应方式:
    • 格式校验
      • 客户端:使用Js技术,利用正则表达式校验
      • 服务端:使用校验框架
    • 逻辑校验
      • 客户端:使用ajax发送要校验的数据,在服务端完成逻辑校验,返回校验结果
      • 服务端:接收到完整的请求后,在执行业务操作前,完成逻辑校验

1.1.3 表单校验规则

  • 长度:例如用户名长度,评论字符数量
  • 非法字符:例如用户名组成
  • 数据格式:例如Email格式、 IP地址格式
  • 边界值:例如转账金额上限,年龄上下限
  • 重复性:例如用户名是否重复

1.1.4 表单校验框架

  • JSR(Java Specification Requests):Java 规范提案

    303:提供bean属性相关校验规则

  • JSR规范列表

    • 企业应用技术
       Contexts and Dependency Injection for Java (Web Beans 1.0) (JSR 299)
       Dependency Injection for Java 1.0 (JSR 330)@postConstruct, @PreDestroy
       Bean Validation 1.0 (JSR 303)
       Enterprise JavaBeans 3.1 (includes Interceptors 1.1) (JSR 318)
       Java EE Connector Architecture 1.6 (JSR 322)
       Java Persistence 2.0 (JSR 317)
       Common Annotations for the Java Platform 1.1 (JSR 250)
       Java Message Service API 1.1 (JSR 914)
       Java Transaction API (JTA) 1.1 (JSR 907)
       JavaMail 1.4 (JSR 919)
    • Web应用技术
       Java Servlet 3.0 (JSR 315)
       JavaServer Faces 2.0 (JSR 314)
       JavaServer Pages 2.2/Expression Language 2.2 (JSR 245)
       Standard Tag Library for JavaServer Pages (JSTL) 1.2 (JSR 52)
       Debugging Support for Other Languages 1.0 (JSR 45)
       模块化 (JSR 294)
       Swing应用框架 (JSR 296)
       JavaBeans Activation Framework (JAF) 1.1 (JSR 925)
       Streaming API for XML (StAX) 1.0 (JSR 173)
    • 管理与安全技术
       Java Authentication Service Provider Interface for Containers (JSR 196)
       Java Authorization Contract for Containers 1.3 (JSR 115)
       Java EE Application Deployment 1.2 (JSR 88)
       J2EE Management 1.1 (JSR 77)
       Java SE中与Java EE有关的规范
       JCache API (JSR 107)
       Java Memory Model (JSR 133)
       Concurrency Utilitie (JSR 166)
       Java API for XML Processing (JAXP) 1.3 (JSR 206)
       Java Database Connectivity 4.0 (JSR 221)
       Java Management Extensions (JMX) 2.0 (JSR 255)
       Java Portlet API (JSR 286)
  • Web Service技术
     Java Date与Time API (JSR 310)
     Java API for RESTful Web Services (JAX-RS) 1.1 (JSR 311)
     Implementing Enterprise Web Services 1.3 (JSR 109)
     Java API for XML-Based Web Services (JAX-WS) 2.2 (JSR 224)
     Java Architecture for XML Binding (JAXB) 2.2 (JSR 222)
     Web Services Metadata for the Java Platform (JSR 181)
     Java API for XML-Based RPC (JAX-RPC) 1.1 (JSR 101)
     Java APIs for XML Messaging 1.3 (JSR 67)
     Java API for XML Registries (JAXR) 1.0 (JSR 93)

  • JCP(Java Community Process):Java社区

  • Hibernate框架中包含一套独立的校验框架hibernate-validator

    导入坐标(在最新SpringBoot中已经集成此包,所以不需要配置)

    1
    2
    3
    4
    5
    <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.0.Final</version>
    </dependency>

    springboot依赖(只需导入这个包):

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    </dependency>

    注意:
    tomcat7 :搭配hibernate-validator版本5...Final
    tomcat8.5↑ :搭配hibernate-validator版本6...Final

1.2 快速使用

1. 开启校验

 名称:@Valid 、 @Validated
 类型:形参注解
 位置:处理器类中的实体类类型的方法形参前方
 作用:设定对当前实体类类型参数进行校验
 范例:

1
2
3
4
5
@PutMapping("/updateUser")
public boolean updatetUser(@RequestBody @Valid User user){
System.out.println(user);
return true;
}

2.设置校验规则

 名称:@NotNull
 类型:属性注解 等
 位置:实体类属性上方
 作用:设定当前属性校验规则
 范例:
每个校验规则所携带的参数不同,根据校验规则进行相应的调整
具体的校验规则查看对应的校验框架进行获取

1
2
3
4
5
6
7
@Data
@ApiModel(value = "用户",description = "用户描述类")
public class User {
private Integer id;
@NotNull(message = "姓名不能为null")
private String name;
}

3.获取错误信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@PutMapping("/updateUser")
public boolean updatetUser(@RequestBody @Valid User user, Errors errors){
if (errors.hasErrors()) {
List<FieldError> fieldErrors = errors.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
//获取字段名称
String field = fieldError.getField();
//错误信息
String errorMsg = fieldError.getDefaultMessage();
System.out.println(field+"-----"+errorMsg);
}
}
System.out.println(user);
return true;
}

通过形参Errors获取校验结果数据;

1.3 多规则校验

  • 同一个属性可以添加多个校验器
1
2
3
4
@NotNull(message = "请输入您的年龄")
@Max(value = 60,message = "年龄最大值不允许超过60岁")
@Min(value = 18,message = "年龄最小值不允许低于18岁")
private Integer age;//员工年龄
  • 3种判定空校验器的区别

image-20200506160725709

  • 其他校验注解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @AssertFalse 验证注解的元素值是 false
    @AssertTrue 验证注解的元素值是 true
    @DecimalMax(value=x) 验证注解的元素值小于等于指定的十进制value值
    @DecimalMin(value=x) 验证注解的元素值大于等于指定的十进制value值
    @Digits(integer=整数位数, fraction=小数位数)验证注解的元素值的整数位数和小数位数上限
    @Future 验证注解的元素值(日期类型)比当前时间晚
    @Max(value=x) 验证注解的元素值小于等于指定的 value值
    @Min(value=x) 验证注解的元素值大于等于指定的 value值
    @NotNull 验证注解的元素值不是 null
    @Null 验证注解的元素值是 null
    @Past 验证注解的元素值(日期类型)比当前时间早
    @Pattern(regex=正则表达式) 验证注解的元素值不指定的正则表达式匹配
    @Size(min=最小值, max=最大值) 验证注解的元素值的在 min 和 max (包含)指定区间之内,如字符长度、集合大小
    @Valid 该注解主要用于字段为一个包含其他对象的集合或map或数组的字段,或该字段直接为一个其他对象的引用,这样在检查当前对象的同时也会检查该字段所引用的对象。
    @NotEmpty 验证注解的元素值不为 null 且不为空(字符串长度不为 0、集合大小不为 0)
    @Range(min=最小值, max=最大值)验证注解的元素值在最小值和最大值之间
    @NotBlank 验证注解的元素值不为空(不为 null、去
    除首位空格后长度为 0),不同于@NotEmpty, @NotBlank 只应用于字符串且在比较时会去除字符串的空格
    @Length(min=下限, max=上限) 验证注解的元素值长度在 min 和 max 区间内
    @Email 验证注解的元素值是 Email,也可以通过正则表达式和 flag 指定自定义的 email 格式

    常用注解如下:

    Constraint 详细信息
    @Valid 被注释的元素是一个对象,需要检查此对象的所有字段值
    @Null 被注释的元素必须为 null
    @NotNull 被注释的元素必须不为 null
    @AssertTrue 被注释的元素必须为 true
    @AssertFalse 被注释的元素必须为 false
    @Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @Size(max, min) 被注释的元素的大小必须在指定的范围内
    @Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
    @Past 被注释的元素必须是一个过去的日期
    @Future 被注释的元素必须是一个将来的日期
    @Pattern(value) 被注释的元素必须符合指定的正则表达式
    @Email 被注释的元素必须是电子邮箱地址
    @Length 被注释的字符串的大小必须在指定的范围内
    @NotEmpty 被注释的字符串的必须非空
    @Range 被注释的元素必须在合适的范围内
    @NotBlank 被注释的字符串的必须非空
    @URL(protocol=,host=, port=,regexp=, flags=) 被注释的字符串必须是一个有效的url
    @CreditCardNumber 被注释的字符串必须通过Luhn校验算法,银行卡,信用卡等号码一般都用Luhn计算合法性

1.4 嵌套校验

 名称:@Valid
 类型:属性注解
 位置:实体类中的引用类型属性上方
 作用:设定当前应用类型属性中的属性开启校验
 范例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Data
@ApiModel(value = "用户",description = "用户描述类")
public class User {
@NotNull(message = "id不能为空")
private Integer id;
@NotNull(message = "姓名不能为null")
private String name;

@NotNull(message = "请输入姓名")
@Max(value = 60,message = "年龄最大值不允许超过60")
@Min(value = 18,message = "年龄最小值为18")
private Integer age;
@Email
private String email;
@Valid//用于嵌套的对象的校验
private Address address;
}

 注意:开启嵌套校验后,被校验对象内部需要添加对应的校验规则

1.5 分组校验

​ 但日常系统中对于不同模块可能对于同一字段合法性校验也会不同,例如用户(User)在注册时可能对于是否邮件填写敏感,而用户添加课程学习列表时也只对用户当前添加课程关心,这样我们之前统一的校验就不起作用了,而hibernate提供的分组功能就能帮助我们实现.直接上代码。

  • 同一个模块,根据执行的业务不同,需要校验的属性会有不同
    • 新增用户
    • 修改用户
  • 对不同种类的属性进行分组,在校验时可以指定参与校验的字段所属的组类别
    • 定义组(通用)
    • 为属性设置所属组,可以设置多个
    • 开启组校验

定义一个没有任何方法的接口:

1
2
public interface GroupOne {
}

在不同的校验规则中通过groups指定当前校验规则所属的分组:

1
2
@NotEmpty(message = "姓名不能为空",groups = {GroupOne.class})
private String name;//员工姓名

在controller控制方法中直接指定当前方法所属分组即可!

1
2
public String addEmployee(@Validated({GroupOne.class}) Employee employee){
}