文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot参数校验的最佳实战教程

2024-04-02 19:55

关注

前言

我们这里使用hibernate-validator作为对象参数验证器,所以在正式介绍SpringBoot参数验证之前,需要先简单了解一下hibernate-validator的使用。

hibernate-validator基本使用

引入依赖


<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.17.Final</version>
</dependency>
<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
</dependency>

编写需要验证对象

验证要求 person对象的用户名不能为空,年龄在1-150岁之间。


@Data
public class Person {

    @NotBlank(message = "username must not be null")
    private String username;

    @Min(value = 1, message = "age must be >= 1")
    @Max(value = 150, message = "age must be < 150")
    private Integer age;
}

验证对象属性是否符合要求


    
    public Validator validator() {
        ValidatorFactory validatorFactory =
                Validation
                        .byProvider(HibernateValidator.class)
                        .configure()
                        // 验证属性时,如果有一个验证不通过就返回,不需要验证所有属性
                        .addProperty("hibernate.validator.fail_fast", "true")
                        .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

    @Test
    public void test() throws Exception {
        Person person = new Person();
        Set<ConstraintViolation<Person>> validate = validator().validate(person);
        validate.forEach(errorParam -> {
            System.out.println(errorParam.getMessage());
        });
    }
  1. 我们只需要验证的对象实例即可完成对象验证,如果验证成功,那么返回一个空的集合,如果验证失败,会返回具体的验证失败的属性信息。
  2. 我们输出验证失败的错误信息如下:

username must not be null

验证规则

validator提供了大量的验证注解供我们使用,主要以下几类:

空/非空验证

  1. @Null 元素必须为空
  2. @NotNull 元素不能为空,空字符串""是非空

以下所有验证规则都在元素非空的时候才会进行验证,如果传入的元素为空,验证都会通过。

bool

  1. @AssertTrue 元素必须为true
  2. @AssertFalse 元素必须为false

时间

  1. @Future 元素必须是未来的某个时间。
  2. @FutureOrPresent 元素必须是未来或者现在的某个时间。
  3. @Past 元素必须是过去的某个时间。
  4. @PastOrPresent 元素必须是过去或者现在的某个时间。

数学

数字类型可以是BigDecimal、BigInteger、CharSequence 、byte 、 short 、 int 、 long以及它们各自的包装器类型

  1. @Digits 元素必须是该数字类型下可以被接受的数值范围内。
  2. @Negative 元素必须是负数
  3. @NegativeOrZero  元素必须小于等于0
  4. @Positive 元素必须大于0
  5. @PositiveOrZero 元素必须大于等于0
  6. @Max,@Min 元素的大小必须符合指定大小

字符串

  1. @Email 邮箱格式验证
  2. @NotBlack 验证字符串非空,空字符串""也属于空
  3. @Pattern 字符串正则验证

模板正则

validator提供了字符串模板正则的注解,这里提供一份常用的正则表达式,大家可以直接作为常量工具类放到项目里使用


public interface ValidatorPattern {

    
    String REGEX_USERNAME = "^[a-zA-Z]\w{5,17}$";

    
    String REGEX_PASSWORD = "^(?=.*[a-zA-Z])(?=.*[0-9])[A-Za-z0-9._~!@#$^&*]{6,12}$";

    
    String REGEX_MOBILE = "^[1][34578]\d{9}$";

    
    String REGEX_EMAIL = "^.+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\.)+[a-zA-Z]{2,}$";

    
    String REGEX_CHINESE = "^[\u4e00-\u9fa5],*$";

    
    String REGEX_ID_CARD = "(^\d{18}$)|(^\d{15}$)";

    
    String REGEX_URL = "http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?";

    
    String REGEX_IP_ADDR = "(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)";

    
    String LICENSE_NO = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z][A-Z][A-Z0-9]{4,5}[A-Z0-9挂学警港澳]$";

    
    String NAME = "[\u4e00-\u9fa5\u00b7\sA-Za-z]{1,15}$";

    
    String EMOJI = "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]";

    
    String NUMBER = "^[0-9]*$";

    
    String N_NUMS = "^\d{n}$";

}

SpringBoot整合hibernate-validator

引入依赖

这个不再赘述,直接拷贝上文的依赖信息

配置hibernate-validator验证器对象

在配置类中加入hibernate-validator验证器对象


    @Bean
    @Primary
    public Validator validator() {
        ValidatorFactory validatorFactory =
                Validation
                        .byProvider(HibernateValidator.class)
                        .configure()
                        .addProperty("hibernate.validator.fail_fast", "true")
                        .buildValidatorFactory();
        return validatorFactory.getValidator();
    }

借助SpringMVC统一异常处理处理参数校验结果

配置好后,Spring会自动帮助我们进行参数验证,如果参数验证不通过,会抛出BindException异常,我们刚刚手动验证时的Set<ConstraintViolation<Person>>通过该异常获取。

我们这可以通过借助SpringMVC统一异常处理的能力处理这个异常


@Slf4j
@RestControllerAdvice
public class BaseExceptionHandler {
    
    @ResponseStatus(org.springframework.http.HttpStatus.PAYMENT_REQUIRED)
    @ExceptionHandler(BindException.class)
    public R<Void> handler(BindException e) {
        String defaultMsg = e.getBindingResult().getAllErrors()
                .stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(":"));
        log.warn(defaultMsg);
        return R.of(IRespCode.PARAMETERS_ANOMALIES.getCode(), e.getMessage());
    }
}

使用参数校验

我们只需要在校验参数的方法传参上标注@Valid或者@Validated都行


    @PostMapping("register")
    public R<Void> register(@Valid @RequestBody Person person) {
        // todo 
        return R.ok();
    }

分组校验

那么@Valid和@Validated有什么区别呢?

Validated比Valid多了一个属性,这个属性用于分组校验使用


public @interface Valid {
}
public @interface Validated {
    Class<?>[] value() default {};
}

啥叫分组校验?

就是一个实体类中的属性,在不同的方法传参中,方法的对属性的要求不同。

比如说,Person类中有三个属性,一个是用户名称,一个是邮箱,一个是年龄。

在注册用户接口中,用户名称,邮箱和年龄都不能为空,但是在更改用户的信息接口中,用户的年龄和邮箱都可以为空,但是用户名称不能为空。

这时候,我们就可以按照对属性校验的要求进行分组。

新建一个RegisterGroup分组,该分组只是一个空的接口,仅仅用于标记该校验要求


public interface RegisterGroup {
}

对校验要求进行分组


@Data
public class Person {

    @NotBlank(message = "username must not be null")
    private String username;

    @Min(value = 1, message = "age must be >= 1")
    @Max(value = 150, message = "age must be < 150")
    @NotNull(message = "age must not be null", groups = RegisterGroup.class)
    private Integer age;

    @Email(message = "email format error")
    @NotBlank(message = "email must not be null",groups = RegisterGroup.class)
    private String email;
}

方法调用时,加入分组要求


    @PostMapping("register")
    public R<Void> register(@Validated(value = RegisterGroup.class) @RequestBody Person person) {
        // todo
        return R.ok();
    }

这种方式其实不推荐使用,我在标题的时候,也已经标记为“过时”,因为,我们完全可以为这两个不同的接口创建两个不同的实体类,而不是使用分组对校验要求进行隔离,因为实际生产环境中,分组可能有非常多个,这会为我们的程序的可读性埋下隐患,后期开发人员难以维护,而且对于自动生成API文档也不友好。大家对于分组只需要了解即可,不建议在项目开发中使用。

总结

到此这篇关于SpringBoot参数校验的文章就介绍到这了,更多相关SpringBoot参数校验内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯