Java之验证框架

分层验证与JavaBean验证

分层验证模型

image-20201109133226735

Java Bean验证模型

image-20201109133312063

Bean Validation简介

Bean Validation为JavaBean验证定义了相应的元数据模型和API。 –维基百科

常用约束注解

  • 空值校验类:@Null,@NotNull,@NotEmpty,@NotBlank等
  • 范围校验类:@Min,@Size,@Digits,@Future,@Negative等
  • 其他校验类:@Email,@URL,@AssertTrue,@Pattern等

代码案例

引入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!--Validation相关依赖-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.0.Final</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.3.6.Final</version>
</dependency>

<!--el表达式-->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.6</version>
</dependency>
  • 空值约束

    • @NotNull

      1
      2
      3
      4
      5
      /**
      * 用户id
      */
      @NotNull(message = "用户ID不能为空", groups = LoginGroup.class)
      private String userId;
  • @NotBlank

    • 注意:自动去掉字符串前后空格后验证是否为空
    1
    2
    3
    4
    5
    6
    /**
    * 用户密码
    * NotBlank 自动去掉字符串前后空格后验证是否为空
    */
    @NotBlank(message = "用户密码不能为空")
    private String password;
  • @NotEmpty

    • 不会自动去掉前后空格
    1
    2
    3
    4
    5
    6
    /**
    * 用户名
    * NotEmpty 不会自动去掉前后空格
    */
    @NotEmpty(message = "用户名不能为空")
    private String userName;
  • 范围约束

    • @Min@Max

      • 最小和最大
      1
      2
      3
      4
      5
      6
      /**
      * 年龄
      */
      @Min(value = 18, message = "年龄不能小于18岁")
      @Max(value = 60, message = "年龄不能大于60岁")
      private Integer age;
  • @Size

    1
    2
    3
    4
    5
    /**
    * 好友列表
    */
    @Size(min = 1, message = "不能少于一个好友")
    private List<UserInfo> friends;
  • @Length

    1
    2
    3
    4
    5
    /**
    * 用户密码
    */
    @Length(min = 6, max = 20, message = "密码长度不能少于6位,多于20位")
    private String password;
  • 其他约束

    • @Past

      1
      2
      3
      4
      5
      /**
      * 生日
      */
      @Past(message = "生日不能为未来时间点")
      private Date birthday;
  • @Email

    1
    2
    3
    4
    5
    /**
    * 邮箱
    */
    @Email(message = "邮箱必须为有效邮箱")
    private String email;
  • 级联约束

    • @Valid

      1
      2
      3
      4
      5
      /**
      * 好友列表
      * 级联验证:@Valid
      */
      private List<@Valid UserInfo> friends;
  • 分组约束

    • groups

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      package com.java.example.validation;

      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      import lombok.experimental.Accessors;

      import javax.validation.constraints.Email;
      import javax.validation.constraints.NotNull;

      /**
      * 待验证对象实体类
      * 用户信息类
      *
      * @author jingLv
      * @date 2020/11/09
      */
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Accessors(chain = true)
      public class UserInfo {

      /**
      * 登录场景
      */
      public interface LoginGroup {
      }

      /**
      * 注册场景
      */
      public interface RegisterGroup {

      }

      /**
      * 用户id
      */
      @NotNull(message = "用户ID不能为空", groups = LoginGroup.class)
      private String userId;

      /**
      * 邮箱
      */
      @NotNull(message = "邮箱不能为空", groups = RegisterGroup.class)
      @Email(message = "邮箱必须为有效邮箱")
      private String email;
      }
  • 组序列约束

    • @GroupSequence

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      package com.java.example.validation;

      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      import lombok.experimental.Accessors;

      import javax.validation.GroupSequence;
      import javax.validation.constraints.Email;
      import javax.validation.constraints.NotNull;
      import javax.validation.groups.Default;

      /**
      * 待验证对象实体类
      * 用户信息类
      *
      * @author jingLv
      * @date 2020/11/09
      */
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      @Accessors(chain = true)
      public class UserInfo {

      /**
      * 登录场景
      */
      public interface LoginGroup {
      }

      /**
      * 注册场景
      */
      public interface RegisterGroup {

      }

      /**
      * 组排序场景
      */
      @GroupSequence({LoginGroup.class, RegisterGroup.class, Default.class})
      public interface Group {

      }

      /**
      * 用户id
      */
      @NotNull(message = "用户ID不能为空", groups = LoginGroup.class)
      private String userId;
      /**
      * 邮箱
      */
      @NotNull(message = "邮箱不能为空", groups = RegisterGroup.class)
      @Email(message = "邮箱必须为有效邮箱")
      private String email;
      }

  • 校验参数

    • @Valid约束对象(入参)需要验证
  • 校验返回值

    • @Valid约束对象(出参)需要验证
  • 校验构造方法

    • @Valid约束对象(构造函数参数)需要验证

实战案例

完成验证的步骤:

  1. 约束注解的定义
  2. 约束验证规则(约束验证器)
  3. 约束注解的声明
  4. 约束验证流程

自定义手机号约束注解:

  1. 定义@interface Phone注解
  2. 实现约束验证器PhoneValidator.java
  3. 声明@Phone约束注解
  4. 执行手机号约束验证流程

规范编程的常见名词

JCP、JSR简介

JCP(Java Community Process)成立与1998年,是使有兴趣的各方参与定义Java的特征和未来版本的正式过程

JCP使用JSR(Java规范请求,Java Specification Request)作为正式规范文档,描述被提议加入到Java体系中的规范和技术。

​ – 维基百科

有关数据校验:JSR303、JSR349、JSR380

  • JSR303,Bean Validation 1.0,jdk1.6
  • JSR349,Bean Validation 1.1,jdk1.7
  • JSR380,Bean Validation 2.0,jdk1.8

Bean Validation与Hibernate Validator

  • Bean Validation 1.0参考实现:Hibernate Validator 4.3.1.Final
  • Bean Validation 1.1参考实现:Hibernate Validator 5.1.1.Final
  • Bean Validation 2.0参考实现:Hibernate Validator 6.0.1.Final

Hibernate Validator与Spring Validation

Spring Validation在Hibernate Validator的基础上,对其进行了二次封装,以满足在Spring环境中更简单、高效的对数据进行验证。