• spring-boot---validation,参数校验,分组,嵌套,各种类型


    写在前面:
    参数校验基本上是controller必做的事情,毕竟前端传过来的一切都不可信。 但是每次if(StrUtil.isNotNull())啥的有时候多还难写。validation可以简化这一操作。

    项目构建

    采用boot3,主要依赖为spring web 和validation
    在这里插入图片描述

    主要依赖:

            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-validationartifactId>
            dependency>
    
    • 1
    • 2
    • 3
    • 4

    项目结构
    在这里插入图片描述

    问题展示

    先来个简单的案例

    @RestController
    public class ValidationController {
    
        @GetMapping("/get")
        public String get(String name,String age){
            System.out.println(name);
            System.out.println(age);
            return "ok";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    点击这个就可以发送请求了
    在这里插入图片描述
    发送出去不会做任何校验
    在这里插入图片描述
    这个的处理我们可以选择加上@RequestParam注解。
    @RequestParam默认属性require为true,就是必须要传值,

     public String get(@RequestParam String name,@RequestParam String age)
    
    • 1

    报错返回
    在这里插入图片描述
    封装成实体类也是一样的。

    但是这样只能做非null判断,不能做复杂的判断。
    在body里面的时候更加不会校验了
    在这里插入图片描述

    validation使用

    那么validation又如何做到呢。

    快速入门

    需求:get请求中,name长度在2-10,age在10-100岁之间且都不为null。

        @GetMapping("/get")
        public String get(@Length(max = 10,min = 2) String name,
                          @Min(10)@Max(100) String age){
            System.out.println("name = " + name);
            System.out.println("age = " + age);
            return "ok";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    为null发送,好ok一点用没有。
    在这里插入图片描述
    我查资料发现需要参数前面加上启动校验@Validated或者@Valid注解,但是无论我怎么放到都是没有校验。
    全部无效。
    在这里插入图片描述
    我之前研究了半天,然后才发现,如果想要这样校验的话,需要在controller类上面加上@Validated且Valid都不行。
    在这里插入图片描述
    如果是实体类接收就不一样了。
    直接在方法就可以了
    在这里插入图片描述

    注释

    到这里基本使用应该就差不多知道了。
    现在来进行注解的学习。

    注解通用属性
    基本上都有的

    属性描述
    message错误返回描述
    groups分组,可以进行更加灵活的选择。
    payload

    无参注解,无必须传的值

    注解限制类型
    @Null限制只能为null接收任何类型,这个应该用的比较少
    @NotNull限制必须不为null接收任何类型
    @AssertFalse限制必须为false支持的类型包括 boolean 和 Boolean。null 元素被视为有效。
    @AssertTrue限制必须为true支持的类型包括 boolean 和 Boolean。null 元素被视为有效。
    @Future限制必须是一个将来的日期大部分的时间类如果Date、Calendar、Instant、LocalDate等。null 元素被视为有效
    @Past限制必须是过去的时刻、日期或时间和上面一样
    @PastOrPresent带注释的元素必须是过去或现在的时刻、日期或时间同上
    @NotEmpty带批注的元素不得为 null和空CharSequence(计算字符序列的长度)Collection (集合大小)Map (大小)数组(计算数组长度)
    @NotBlank带批注的元素不得且 null 必须至少包含一个非空格字符CharSequence
    @Positive带注释的元素必须是严格的正数(即 0 被视为无效值)。BigDecimal、BigInteger、byteintlong、 short及其floatdouble各自的包装器
    @PositiveOrZero正数或0同上

    大小注解,用于限值大小

    注解限制类型
    @DecimalMax(value,inclusive)限制必须为一个不大于指定值的value数字,inclusive:指定指定的最小值是包含的还是排除的true为不包括最小值BigDecimal、BigInteger、CharSequence、byte、 shortintlong及其各自的包装器,请注意, double 由于舍入错误,不支持 (某些 float 提供程序可能会提供一些近似支持)。null 元素被视为有效。
    @DecimalMin(value,inclusive)限制必须为一个不小于指定值的value数字,inclusive:最大值是否包括同上
    @Digits(integer,fraction)必须是接受范围内的数字,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction同上
    @Max(value)限制必须为一个不大于指定值的数字同上
    @Min(value)限制必须为一个不小于指定值的数字同上
    @Length(min = 6, max = 16)指定传入的字符串的长度字符串
    @Size(max,min)限制字符长度必须在min到max之间 【不是数字】同notempty,集合类数组和字符
    @Range带批注的元素必须在适当的范围内。应用于数值或数值的字符串表示形式。

    基于正则类型

    注解限制类型
    @Pattern(value)限制必须符合指定的正则表达式CharSequence,null有效
    @Email验证注解的元素值是Email,可选值regexp,flags也可以通过正则表达式和flag指定自定义的email格式。因为每个人要求的邮箱可能格式也不一样,如我可以通过regexp设置后缀必须为@qq.comCharSequence,null有效
    @CreditCardNumber信用卡校验同上
    @URL批注的字符串是否为 URL基于正则表达式的 。同上
    @UUID批注的字符序列是否为有效的 UUID,version指定版本variant变体,letterCase所需的字母大小写 默认情况下只有小写有效,allowNil如果 nil UUID 有效 根据默认值 nil UUID 00000000-0000-0000-0000-000000000000 有效,allowEmpty允许空字符串。默认情况下不允许空字符串

    脚本注解
    @ScriptAssert
    它根据批注元素计算脚本表达式。此约束可用于实现验证例程,脚本表达式可以用任何脚本或表达式语言编写,在类路径上可以找到 JSR 223 (“JavaTM 平台脚本”)兼容引擎。下面的清单显示了使用 JDK 附带的 JavaScript 引擎的示例:
    我看到的时候给我震惊了一下,他注解写的啥??任何表达式语言??不过可能是我没见过世面,或者是知识点用的少,java6就支持JavaScript。不过一般很少用吧。

    下面是一个校验时间的脚本

    @ScriptAssert(lang = "javascript", script = "_this.startDate.before(_this.endDate)")   
    public class CalendarEvent {
         private Date startDate;
         private Date endDate;
         //...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意!!!java11开始就移除了NashornScriptEngineFactory,所以11以上需要添加依赖才可以使用javascript
    需要新增

            <dependency>
                <groupId>org.openjdk.nashorngroupId>
                <artifactId>nashorn-coreartifactId>
                <version>15.4version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    没有通过

    在这里插入图片描述
    修改时间通过了
    在这里插入图片描述

    Valid与Validated区别

    Validated是Valid的加强版

    使用范围

    经过我的层层验证

    1. controller类上:
      在controller类上只有使用validated,将开启所有的路径参数验证,对实体类(路径和body)无效
    2. 方法上:
      全部无效,无论是路径还说body,2个注解都没用。
    3. 入参上:
      只有在对body或者路径参数实体类或者添加注解才有效,2个都有效,对单独的类型无效
    4. 实体类的属性上
      Valid有效,且路径参数有效,body无效,body需要自己参数开启,无论参数是否加验证注解

    两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能。

    分组

    @Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制。没有添加分组属性时,默认验证没有分组的验证属性。Valid是不能进行分组的,灵活性更差。

    public class DemoQuery {
        @Length(max = 10, min = 2,groups = {Demo1.class, Demo2.class},message = "name长度不符合要求")
        private String name;
        @Min(value = 10,groups = {Demo1.class}) @Max(100)
        @NotNull
        private Integer age;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
        @PostMapping("/post2")
        public String post2(@Validated({Demo2.class}) @RequestBody DemoQuery query, @NotNull String id) {
            System.out.println("name = " + query.getName());
            System.out.println("age = " + query.getAge());
            System.out.println("id = " + id);
            return "ok";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    不通过
    在这里插入图片描述

    通过
    在这里插入图片描述
    改为demo1
    在这里插入图片描述

    嵌套验证

    新增一个类

    @Data
    public class NestedQuery {
    
        @NotNull
        private String id;
    
        @Valid
        @NotNull
        private DemoQuery querys;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
        @GetMapping("/nested")
        public String nested(@Validated NestedQuery query, BindingResult bindingResult) {
            System.out.println("id = " + query.getId());
            System.out.println("query = " + query.getQuerys());
            System.out.println(bindingResult);
            return "ok";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    发送返回的居然是ok,
    在这里插入图片描述
    但是在控制台,验证说出错了,说明嵌套的错误不会直接返回,而是会记录。需要自己处理一下。

    在这里插入图片描述

    Assert.isTrue(!bindingResult.hasErrors(),"参数错误");
    
    • 1

    在这里插入图片描述
    结束:收工,累死了。

  • 相关阅读:
    commons-io版本变动在windows环境下引发的NTFS ADS separator问题
    【计算机网络】网络层-控制平面(学习笔记)
    [Python]Flask简介与gunicorn部署
    【MATLAB图像处理实用案例详解(12)】——基于纹理特征的指纹识别方法
    制作一个简单HTML宠物猫网页(HTML+CSS)
    MySQL学习系列(1)-每天学习10个知识
    KVM 教程
    【Linux】进程间通信——管道
    vue重修之路由【下】
    如何利用Dpabi,AFNI,FSL软件计算种子点的功能连接?
  • 原文地址:https://blog.csdn.net/qq_56717234/article/details/133138965