入参校验1

news2024/12/30 2:36:27

文章目录

    • 一、简介
      • 1、快速失败(Fail Fast)
    • 二、单字段类入参校验
    • 三、JSON实体类校验
      • 1、注解解析
      • 2、案例
        • 1、简单校验
        • 2、分组校验
        • 3、嵌套校验
        • 4、集合校验
        • 5、自定义校验
    • 四、相关
      • 1、源码文件
      • 2、参考地址


一、简介

1、快速失败(Fail Fast)

Spring Validation 默认会校验完所有字段,然后才抛出异常。但通常情况下我们希望遇到校验异常就立即返回,此时可以通过一些简单的配置,开启 Fali Fast 模式,一旦校验失败就立即返回。

@Configuration
public class ValidatorConfiguration {
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                // 快速失败模式
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}

二、单字段类入参校验

这类主要依赖于@RequestParam进行入参的校验

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestParam {
    @AliasFor("name")
    String value() default "";

    @AliasFor("value")
    String name() default "";

    boolean required() default true;

    String defaultValue() default "\n\t\t\n\t\t\n\ue000\ue001\ue002\n\t\t\t\t\n";
}

案例:

@GetMapping("/test")
public void test(@RequestParam(value = "id", required = true) String id,
                 @RequestParam(value = "name", required = false) String name) {
    log.info("id,:{}", id);
}
  • value:请求中传入参数的名称,如果不设置后台接口的value值,则会默认为该变量名。比如上图中第一个参数如果不设置value=“page”,则前端传入的参数名必须为pageNum,否则在后台接口中pageNum将接收不到对应的数据

  • required:该参数是否为必传项。默认是true,表示请求中一定要传入对应的参数,否则会报404错误,如果设置为false时,当请求中没有此参数,将会默认为null,而对于基本数据类型的变量,则必须有值,这时会抛出空指针异常。如果允许空值,则接口中变量需要使用包装类来声明。

  • defaultValue:参数的默认值,如果请求中没有同名的参数时,该变量默认为此值。注意默认值可以使用SpEL表达式,如"#{systemProperties[‘java.vm.version’]}"

三、JSON实体类校验

1、注解解析

validation-api中的注解

注解说明适用类型
@AssertFalse限制必须是falseboolean
Boolean:not null时才校验
@AssertTrue限制必须是trueboolean
Boolean:not null时才校验
@Max(value)限制必须为一个小于等于value指定值的整数,value是long型byte/short/int/long/float/double及其对应的包装类;
包装类对象not null时才校验
@Min(value)限制必须为一个大于等于value指定值的整数,value是long型byte/short/int/long/float/double及其对应的包装类;
包装类对象not null时才校验
@DecimalMax(value)限制必须小于等于value指定的值,value是字符串类型byte/short/int/long/float/double及其对应的包装类;
包装类对象not null时才校验
@DecimalMin(value)限制必须大于等于value指定的值,value是字符串类型byte/short/int/long/float/double及其对应的包装类;
包装类对象not null时才校验
@Digits(integer, fraction)限制必须为一个小数(其实整数也可以),且整数部分的位数不能超过integer,小数部分的位数不能超过fraction。integer和fraction可以是0。byte/short/int/long/float/double及其对应的包装类;
包装类对象必须not null时才校验
@Null限制只能为null任意对象类型(比如基本数据类型对应的包装类、String、枚举类、自定义类等);
不能是8种基本数据类型
@NotNull限制必须不为null任意类型(包括8种基本数据类型及其包装类、String、枚举类、自定义类等);
但是对于基本数据类型,没有意义
@Size(min, max)限制Collection类型或String的长度必须在min到max之间,包含min和maxCollection类型(List/Set)
String
@Pattern(regexp)限制必须符合regexp指定的正则表达式String
@Future限制必须是一个将来的日期Date/Calendar
@Past限制必须是一个过去的日期Date/Calendar
@Valid校验任何非原子类型,标记一个对象,表示校验对象中被注解标记的对象(不支持分组功能)需要校验成员变量的对象,比如@ModelAttribute标记的接口入参

2、案例

1、简单校验

@PostMapping("/test")
public void test(@Validated @RequestBody TestTableDTO dto) {
    log.info(JSON.toJSONString(dto));
}
import lombok.Data;
import javax.validation.constraints.*;

@Data
public class TestTableDTO {
    
    @NotNull(message = "id:为空")
    private Integer id;

    //  能通过("name":"",)
    @NotNull(message = "name:为空")
    private String name;

    @NotBlank(message = "address:为空")
    private String address;

    @Max(value = 10, message = "sex:大于10")
    private Integer sex;

    @Min(value = 90, message = "weight:小于90")
    private Integer weight;

    @Size(min = 120, max = 150, message = "height:范围120~150")
    private Integer height;
}

2、分组校验

分局不同的校验组,进行不同规则校验

@PostMapping("/test")
public void test(@Validated(value = InfoGroup.class) @RequestBody TestTableDTO dto) {
    log.info(JSON.toJSONString(dto));
}
@PostMapping("/get")
public void get(@Validated(value = StringGroup.class) @RequestBody TestTableDTO dto) 
    log.info(JSON.toJSONString(dto));
}

校验实体类

import lombok.Data;

import javax.validation.constraints.*;

@Data
public class TestTableDTO {

    @NotNull(message = "id:为空")
    private Integer id;

    @NotBlank(message = "address:为空",groups = InfoGroup.class)
    private String address;

    @Max(value = 10, message = "sex:大于10",groups = StringGroup.class)
    private Integer sex;
}

规则类InfoGroup

public interface InfoGroup {
    
}

规则类StringGroup

public interface StringGroup {
    
}

3、嵌套校验

Controller

@PostMapping("/test")
public void test(@Validated @RequestBody TestTableDTO dto) {
    log.info(JSON.toJSONString(dto));
}

实体类:

import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;

@Data
public class TestTableDTO {

    @NotNull(message = "id:为空")
    private Integer id;

    @NotBlank(message = "address:为空", groups = InfoGroup.class)
    private String address;

    @Max(value = 10, message = "sex:大于10", groups = StringGroup.class)
    private Integer sex;

    @Valid
    private List<Course> course;

    @Data
    public static class Course {
        @NotBlank(message = "code:为空")
        private String code;
        @NotBlank(message = "name:为空")
        private String name;
    }
}

入参

{
    "id": 1,
    "name": "ddd",
    "address": "1",
    "sex": 9,
    "course": [
        {
            "code": "001",
            "name": "张三"
        },
        {
            "code": "002",
            "name": "李四"
        }
    ]
}

4、集合校验

如果接口请求体直接传递 JSON 数组给后台,并希望对数组中的每一项都进行参数校验。此时,如果我们直接使用 java.util.Collection 下的 List 或者 Set 来接收数据,参数校验并不会生效。在这种情况下,我们需要使用自定义的 List 集合来接收参数,即包装 List 类型,并声明 @Valid 注解。

不校验类型(错误)

@PostMapping("/test")
public void test(@Validated @RequestBody List<TestTableDTO> dto) {
    log.info(JSON.toJSONString(dto));
}

正解

Controller

@PostMapping("/test")
public void test(@Validated @RequestBody StudentList<TestTableDTO> dto) {
    log.info(JSON.toJSONString(dto));
}

实体类:

import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Data
public class TestTableDTO {

    @NotNull(message = "id:为空")
    private Integer id;

    @NotBlank(message = "address:为空")
    private String address;

    @Max(value = 10, message = "sex:大于10")
    private Integer sex;
}

入参

[
    {
        "id": 1,
        "address": "1",
        "sex": 9
    },
    {
        "id": 1,
        "address": "",
        "sex": 9
    }
]

报错信息

系统异常:JSR-303 validated property 'list[1].address' does not have a corresponding accessor for Spring data binding - check your DataBinder's configuration (bean property versus direct field access)

5、自定义校验

自定义注解@ListValue

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 自定义校验注解
 */
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class}) // 指定校验器,这里不指定时,就需要在初始化时指定
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {

    /**
     * 默认的提示内容
     */
    String message() default "必须提交指定的值哦";

    /**
     * 校验分组
     */
    Class<?>[] groups() default {};

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

    /**
     * 默认值(用于校验器中,数值校验)
     */
    int[] values() default {};
}

自定义校验器ListValueConstraintValidator

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;

/**
 * 指定校验器
 */
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {
    private final Set<Integer> initSet = new HashSet<>();

    /**
     * 初始化方法(将取注解默认值,存到指定位置)
     */
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] values = constraintAnnotation.values();
        for (int value : values) {
            initSet.add(value);
        }
    }

    /**
     * 判断是否校验成功
     *
     * @param value   被校验参数
     * @param context 上下文
     * @return
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        System.out.println(value);
        return initSet.contains(value);
    }
}

入参实体类

import lombok.Data;
import javax.validation.constraints.NotBlank;

@Data
public class TestTableDTO {

    @ListValue(message = "id:为空", values = 1)
    private Integer id;

    @NotBlank(message = "name:为空")
    private String name;
}

Controller层

@PostMapping("/test")
public void test(@Validated @RequestBody TestTableDTO dto) {
    log.info(JSON.toJSONString(dto));
}

测试

PostMan请求

{
    "id":null,
    "name":"张三"
}

测试结果:

在这里插入图片描述

四、相关

1、源码文件

CSDN

https://download.csdn.net/download/weixin_44624117/87796980

2、参考地址

  • https://blog.csdn.net/zqy123456_123/article/details/127109216

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/542197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GPT-4的免费使用方法分享(续)

GPT-4的免费使用方法分享_我爱OJ的博客-CSDN博客 在这篇博客里&#xff0c;我介绍了一些ChatGPT的一些使用方法&#xff0c;但可能有一定的缺陷&#xff0c;有的需要魔法&#xff0c;所以&#xff0c;今天我就来亲测一下&#xff0c;关于ChatGPT的一些免费使用技巧 目录 镜像…

代码随想录算法训练营第九天|KMP算法

记录一下KMP算法&#xff0c;本文摘录自《代码随想录》和部分b站视频帮你把KMP算法学个通透&#xff01;&#xff08;理论篇&#xff09;_哔哩哔哩_bilibili最浅显易懂的 KMP 算法讲解_哔哩哔哩_bilibiliKMP字符串匹配算法2_哔哩哔哩_bilibili KMP算法 主要应用&#xff1a;字…

牛客小白月赛65

题目链接 牛客小白月赛65 A-牛牛去购物&#xff08;枚举&#xff09;B-牛牛写情书&#xff08;字符串&#xff09;C-牛牛排队伍&#xff08;模拟&#xff09;D-牛牛取石子&#xff08;博弈&#xff09;E-牛牛的构造&#xff08;构造&#xff0c;思维&#xff09; A-牛牛去购物…

怎么免费使用 ChatGpt,实用!

最近发现了一个可以免费、轻松使用 ChatGpt 的方法&#xff0c;随即做个记录&#xff0c;留着备忘&#xff0c;以后想用也能随时找到方法。 但是不保证该方法永远有效&#xff0c;仅当下有限&#xff0c;做个记录罢了。 因为我使用的是 windows 自带的浏览器 Microsoft Edge &a…

Android--刷机与adb

目录 一、Android设备启动流程 二、刷机模式介绍 三、Windows命令行 四、adb介绍与配置 五、常用的adb命令 一、Android设备启动流程 Android就是Linux内核(Kernel)Java虚拟机(JVM) Android设备启动就分为两个阶段&#xff1a; Linux启动 1.启动电源以及系统启动&#…

详解c++STL—容器list

目录 1、list基本概念 1.1、概念描述 1.2、结点的组成 1.3、list的优点 1.4、list的缺点 1.5、总结 2、list构造函数 2.1、功能描述 2.2、函数原型 2.3、示例 3、list赋值和交换 3.1、功能描述 3.2、函数原型 3.3、示例 4、list大小操作 4.1、功能描述 4.2、函…

ChatGPT的前世今生——混沌初开

目录 ChatGPT的前世今生——混沌初开ChatCPT简介ChatCPT是什么&#xff1f;ChatCPT的火爆程度ChatCPT火爆的原因1、功能强大&#xff0c;应用范围广泛2、训练数据量大&#xff0c;模型效果好3、优秀的商业模式 OpenAI公司公司创始团队 总结公众号文章链接参考链接&#xff1a; …

03C++类与对象之运算符重载

文章目录 C类与对象之运算符重载与const成员运算符重载赋值运算符重载运算符重载 日期类的实现与运算符重载赋值运算符重载比较类运算符的重载二元运算符-的重载前置和后置重载 总体实现代码const成员const的好处1.防止程序员犯错2.提高代码的复用性 const 成员与函数重载规则 …

Qt文件系统源码分析—第三篇QDir

深度 本文主要分析Windows平台&#xff0c;Mac、Linux暂不涉及 本文只分析到Win32 API/Windows Com组件/STL库函数层次&#xff0c;再下层代码不做探究 本文QT版本5.15.2 类关系图 QTemporaryFile继承QFile QFile、QSaveFile继承QFileDevice QFileDevice继承QIODevice Q…

由浅入深Netty基础知识IO相关

目录 1 stream vs channel2 IO 模型3 零拷贝3.1 传统 IO 问题3.2 NIO 优化 4 AIO4.1 文件 AIO4.2 守护线程4.3 网络 AIO 1 stream vs channel stream 不会自动缓冲数据&#xff0c;channel 会利用系统提供的发送缓冲区、接收缓冲区&#xff08;更为底层&#xff09;stream 仅支…

unity学习遇到的问题:解决VS不能加载Unity脚本,MonoBehaviour是灰色的

电脑出了点问题&#xff0c;然后就重装了&#xff0c;重装之后&#xff0c;从gitee上下载了原来的半截代码&#xff0c;结果发现里面的脚本运行出问题了&#xff0c;仔细一看&#xff0c;MonoBehaviour是灰色的&#xff0c;也就是说&#xff0c;加载不了unity的api了&#xff0…

目标检测复盘 --3. RCNN

RCNN的CNN部分使用AlexNet作为backbone来提取特征&#xff0c;Fast RCNN使用了VGG16来作为backboneRCNN将2000个框送入网络提取特征&#xff0c;Fast RCNN是将图像送入CNN来提取特征得到一个特征图将SS(Selective Search)算法获取的提议框映射到上面的特征图上&#xff0c;获取…

怎么通过ssh连上ipv6的服务器?阿里云怎么配置ipv6?wsl2怎么支持ipv6?

最近在研究ipv6&#xff0c;光调通环境居然让我折腾了好多回&#xff0c;现在终于通了 在这里提一句&#xff0c;IPV6和IPV4是两种东西&#xff0c;不要想着ipv6兼容ipv4&#xff0c;你就当它是全新的东西 1.前置条件 1.1我的电脑能访问ipv6 测试通过就代表你电脑可以访问ip…

Redis 哨兵模式的实现详解

文章目录 高可用&#xff08;HA&#xff09;哨兵模式概述哨兵的搭建伪集群 哨兵1. 复制sentinel.conf文件2. 修改sentinel.conf文件3. 新建sentinel26380.conf4. 启动并关联Redis集群5. 启动Sentinel集群6. 查看 Sentinel 信息7. 查看 Sentinel 配置文件 哨兵优化配置 高可用&…

【腾讯云Finops Crane集训营】降本增效神器Crane实战记录

本章目录 前言一、Crane是什么&#xff1f;Crane的主要功能&#xff1f;FinOps 是什么Prometheus是什么Grafana是什么 二、不得不面对的问题&#xff1a;云上资源效能挑战&#xff01;三、云原生场景下的成本优化挑战&#xff1f;四、K8s原生能力的不足五、Crane智能调度助力成…

Linux命令之vim/vi

目录 vim/vi简介 vi/vim 的使用 操作实例 总结 vim/vi简介 所有的 Unix Like 系统都会内建 vi 文书编辑器&#xff0c;其他的文书编辑器则不一定会存在。但是目前我们使用比较多的是 vim 编辑器。Vim 是从 vi 发展出来的一个文本编辑器。代码补全、编译及错误跳转等方便编程…

i.MX6ULL - 远程视频监控方案实现(nginx-rtmp流媒体服务器、ffmpeg推流)

i.MX6ULL - 远程视频监控配置&#xff08;nginx-rtmp流媒体服务器、ffmpeg推流&#xff09; 目录 i.MX6ULL - 远程视频监控配置&#xff08;nginx-rtmp流媒体服务器、ffmpeg推流&#xff09;1、前言2、buildroot文件系统构建2.1 勾选alsa-utils&#xff08;选做&#xff1a;如果…

桥接模式与NAT模式的区别以及设置静态IP

概述 日常我们都会使用到虚拟机&#xff0c;本文章以VMware虚拟机为例&#xff0c;主要介绍下虚拟机设置桥接模式与NAT模式的区别&#xff0c;并通过示意图进行讲解。并且会介绍如何去设置静态IP。 模式介绍 NAT模式NAT模式下 &#xff0c;创建出来的虚拟机只能访问当前主机…

基于ensp的跨地区的校园网组网方案

本博客是基于模拟器ensp的校园网组网方案&#xff0c;有总校区和分校区&#xff0c;主要用了vlan划分、dhcp、nat、ospf、acl、bgp等技术。首先说一下本博客的局限性&#xff1a; 总校区和分校区之间只是使用的传统的bgp建立连接&#xff0c;这样可以在运营商上看到内网的明细&…

HTTP1.1(七)内容协商和资源表述

一 内容协商和资源表述 ① 铺垫 1) 由于一种资源对应许多种状态,所以客户端接收资源表述的转移时需要进行协商比如&#xff1a;[1]、一个来自中国的用户他的浏览器访问一个页面时得到中文页面[2]、一个其它国家的用户访问同一个页面时得到的是他本国的页面补充&#xff1a;…