日常使用:SpringBoot参数校验,基于JSR303规范

泛型薄雾
• 阅读 2688

我们在写Controller或者Service时经常在方法中写入大量的数据校验代码,如下

       if(StringUtils.isEmpty(pass)){
            return Result.error(ErrorCodeEnum.PASSWORD_EMPTY);
        }else if(!ValidatorUtil.isMobile(mobile)){
            return Result.error(ErrorCodeEnum.MOBILE_PATTERN_WRONG);
        }

不仅浪费时间,还让业务逻辑代码更复杂,下面我们使用JSR303为我们提供的校验工具避免过多的代码校验

JSR303

JSR 303 – Bean Validation 是一个数据验证的规范,不符合规范的将返回一条具体的信息说明该规范的错误
  • 有以下注解为我们提供校验
@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)    被注释的元素必须符合指定的正则表达式
  • 例如:一个封装的登录信息类LoginVo
@Data
public class LoginVo {
    @NotNull
    @Length(max = 11,min = 11)
    private String mobile;//手机号

    @NotNull
    @Length(min = 32)
    private String password;//密码
}
我们使用@NotNull注解为该字段声明为非空,也就是前端传过来的该参数必须有具体的值,不能为null

@Length注解为字段声明字符串最长最短的临界条件,前端传来的数据必须符合要求

  • 最后我们在使用到登录封装类的地方(如Controller参数)打上@Valid注解,就会帮我们的封装类进行校验
public Result doLogin( @Valid LoginVo loginVo)

自定义验证器

为了深入了解JSR303,我们将实现一个自定义验证器(自定义注解实现具体的验证代码),观察它是如何工作的
  • 现在我们需要为登录信息类里的mobile字段进行手机号校验(校验是否为手机号,格式错误返回格式错误信息)
  • 我们将其声明为@IsMobile注解

通过观察上述众多注解,发现验证器的一般代码如下

  • validatedBy:就是要传入一个具体的自定义验证器类(实现验证器逻辑)
  • message方法:这里返回具体的校验失败的错误信息
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(IsMobile.List.class)
@Documented
@Constraint(
        validatedBy = {MobileValidator.class}//这里的validatedBy就是要传入一个具体的自定义验证器类(实现验证器逻辑)
)
public @interface IsMobile {

    boolean required() default true;//可以使用该字段声明是否必须

    String message() default "手机号格式不合法";//这里返回具体的校验失败的错误信息

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
        IsMobile[] value();
    }
}
  • 所以我们需要编写一个类实现验证器逻辑MobileValidator

    验证器需要实现ConstraintValidator接口,该接口用泛型指定两个参数

    • 第一个参数A:就是自定义注解的类
    • T就是具体需要校验的值的类型

重写其中的isValid方法

public class MobileValidator implements ConstraintValidator<IsMobile, String> {

    private boolean required = true;
    @Override
    public void initialize(IsMobile constraintAnnotation) {

    }
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if(required){//如果必须 说明以传入  则进行效验
            return ValidatorUtil.isMobile(s);
        }else {//如果不必须 说明可以没有 先判断是否为空再校验
            if (StringUtils.isEmpty(s)) {
                return false;
            } else return ValidatorUtil.isMobile(s);
        }
    }
}
  • ValidatorUtil 工具类 用户验证
public class ValidatorUtil {
    //使用正则匹配1开头的11位数字
    private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");
//如果匹配返回true,手机号格式正确
    public static boolean isMobile(String s){
        if(StringUtils.isEmpty(s)){
            return false;
        }
        Matcher m = mobile_pattern.matcher(s);
        return m.matches();
    }
}
点赞
收藏
评论区
推荐文章
kenx kenx
3年前
SpringBoot Validation优雅的全局参数校验
前言我们都知道在平时写controller时候,都需要对请求参数进行后端校验,一般我们可能会这样写javapublicStringadd(UserVOuserVO)if(userVO.getAge()null)return"年龄不能为空";if(userVO.getAge()120)r
Stella981 Stella981
3年前
Dubbo使用jsr303框架hibernate
前言,传递的DTO带有hibernatevalidator的注解校验会报错。Dubbo可以集成jsr303标准规范的验证框架,作为验证框架不二人选的hibernatevalidator是大家都会经常在项目中使用的,但是在Dubbo使用是会发生下面这个问题。问题描述背景:使用springmvc做restful,
Easter79 Easter79
3年前
Spring校验@RequestParams和@PathVariables参数
我们在写RestAPI接口时候会用到很多的@RequestParam和@PathVariable进行参数的传递,但是在校验的时候,不像使用@RequestBody那样的直接写在实体类中,我们这篇文章讲解一下如何去校验这些参数。依赖配置要使用JavaValidationAPI,我们必须添加validationap
Wesley13 Wesley13
3年前
Java中的参数验证(非Spring版)
1\.Java中的参数验证(非Spring版)1.1.前言为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入下列的jar包,在参数中添加@Validated,并对Bean对象的参数做不
Stella981 Stella981
3年前
Spring Boot @ControllerAdvice+@ExceptionHandler处理controller异常
需求:  1.springboot 项目restful 风格统一放回json  2.不在controller写trycatch代码块简洁controller层  3.对异常做统一处理,同时处理@Validated校验器注解的异常方法:  @ControllerAdvice注解定义全局异常处理类@ControllerAdvice
Easter79 Easter79
3年前
SpringBoot校验参数
前言做web开发有一点很烦人就是要校验参数,基本上每个接口都要对参数进行校验,比如一些格式校验非空校验都是必不可少的。如果参数比较少的话还是容易处理的一但参数比较多了的话代码中就会出现大量的IFELSE就比如下面这样:!(https://oscimg.oschina.net/oscnet/up5b6e114567bc70667
Stella981 Stella981
3年前
SpringBoot校验参数
前言做web开发有一点很烦人就是要校验参数,基本上每个接口都要对参数进行校验,比如一些格式校验非空校验都是必不可少的。如果参数比较少的话还是容易处理的一但参数比较多了的话代码中就会出现大量的IFELSE就比如下面这样:!(https://oscimg.oschina.net/oscnet/up5b6e114567bc70667
Stella981 Stella981
3年前
SpringBoot中的异常处理与参数校验
兄弟们好,这次来跟老铁交流两个问题,异常和参数校验,在说参数校验之前我们先来说异常处理吧,因为后面参数的校验会牵扯到异常处理这块的内容。异常处理说到异常处理,我不知道大家有没有写过或者遇到过如下的写法。publicvoidsaveUser(){try{//所有的业务内容,目测几百
Easter79 Easter79
3年前
SpringBoot中的异常处理与参数校验
兄弟们好,这次来跟老铁交流两个问题,异常和参数校验,在说参数校验之前我们先来说异常处理吧,因为后面参数的校验会牵扯到异常处理这块的内容。异常处理说到异常处理,我不知道大家有没有写过或者遇到过如下的写法。publicvoidsaveUser(){try{//所有的业务内容,目测几百
SpringBoot如何优雅的进行参数校验(一)
SpringBoot如何优雅的进行参数校验一.为什么要进行参数校验在日常的开发过程中,我们常常需要对传入的参数进行校验,比如在web前后端分离项目中,参数校验有两个方面:前端进行参数校验后端进行参数校验那这两种有什么区别呢?只完成一个可不可以呢?答案是不可
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(