JSR-303统一校验


统一校验需求

前端请求后端接口传输参数,在controllerService中都需要校验,只是分工不同。

  • Contoller中校验请求参数的合法性,包括:必填项校验,数据格式校验,比如:是否是符合一定的日期格式,等。

  • Service中校验业务规则相关的内容,比如:课程已经审核通过所以提交失败。

Service中根据业务规则去校验不方便写成通用代码Controller中则可以将校验的代码写成通用代码。

早在JavaEE6规范中就定义了参数校验的规范,它就是JSR-303,它定义了Bean Validation,即对bean属性进行校验。

SpringBoot提供了JSR-303的支持,它就是spring-boot-starter-validation,它的底层使用Hibernate ValidatorHibernate ValidatorBean Validation 的参考实现。

统一校验实现

添加spring-boot-starter-validation的依赖

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

javax.validation.constraints文件注解如图

如下图所示,直接在类里定义属性的时候添加注解

public class User {

    private String userId;

    //用户名不为空,使用默认提示
    @NotNull
    private String username;

      @NotEmpty(message = "地址不能为空")
      private String address;

    //密码进行长度和格式的验证
    @Size(min=6, max=18, message="密码长度必须在6 ~ 18字符之间")
    @Pattern(regexp="^[a-zA-Z0-9|_]+$", message="密码必须由字母、数字、下划线组成")
    private String password;

    //手机号码自定义提示,使用正则表达式进行匹配
    @Pattern(regexp="^1(3|4|5|7|8|9)\\d{9}$",message="手机号码错误")
    private String mobile;

    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;

}

规则如下:更多详见文档

Constraint 详细信息
@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 被注释的元素必须在合适的范围内

定义好规则后在Controller中使用还需要开启校验,在Controller方法中添加@Validated注解,如下


@PostMapping("/user")
public User createUser(@RequestBody @Validated AddUserDto dto){
  return userService.createUser(dto);
}

分组校验

有时同一属性可能有多个不同校验规则

如:创建用户对象时,用户的id为空,而更新用户对象时,id不能为空。

此时需要用到分组校验,同一个属性定义多个校验规则属于不同的分组

比如:添加用户时使用@NULL规则属于insert分组,更新用户信息使用@NotEmpty规则属于update分组,insert和update是分组的名称

可以创建一个类来定义不同分组。如下:

public class ValidationGroups {

 public interface Inster{};
 public interface Update{};
 public interface Delete{};

}

在定义校验规则时指定分组:

     @NULL(groups = {ValidationGroups.Inster.class},message = "添加用户时id为空")
     @NotEmpty(groups = {ValidationGroups.Update.class},message = "更新用户信息时id不能为空")
    private String userId;

Controller方法中启动校验规则指定要使用的分组名

@PostMapping("/user")
public User createUser(@RequestBody @Validated({ValidationGroups.Inster.class}) AddUserDto dto){
  return userService.createUser(dto);
}

校验规则不满足怎么办?

若javax.validation.constraints包下的校验规则满足不了需求,则需要:

  • 手写校验代码
  • 自定义校验规则注解

文章作者: youzg
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 youzg !
评论
  目录