【Spring Boot】Web开发 — 数据验证

news2024/11/29 21:30:08

Web开发 — 数据验证

对于应用系统而言,任何客户端传入的数据都不是绝对安全有效的,这就要求我们在服务端接收到数据时也对数据的有效性进行验证,以确保传入的数据安全正确。接下来介绍Spring Boot是如何实现数据验证的。

1.Hibernate Validator简介

数据校验是Web开发中的重要部分,目前数据校验的规范、组件非常多,有JSR-303/JSR-349、Hibernate Validator、Spring Validation。

  • JSR(Java Specification Request)规范是Java EE 6中的一项子规范,也叫作Bean Validation。它指定了一整套基于bean的验证API,通过标注给对象属性添加约束条件。
  • Hibernate Validator是对JSR规范的实现,并增加了一些其他校验注解,如@Email、@Length、@Range等。
  • Spring Validation是Spring为了给开发者提供便捷,对Hibernate Validator进行了二次封装。同时,Spring Validation在SpringMVC模块中添加了自动校验,并将校验信息封装进了特定的类中。

JSR定义了数据验证规范,而Hibernate Validator则是基于JSR规范,实现了各种数据验证的注解以及一些附加的约束注解。Spring Validation则是对Hibernate Validator的封装整合。JSR和Hibernate Validator中的常用注解如表所示。

在这里插入图片描述
表中包含了Hibernate Validator实现的JSR-303定义的验证注解和Hibernate Validator自己定义的验证注解,同时也支持自定义约束注解。所有的注解都包含code和message这两个属性。

  • Message定义数据校验不通过时的错误提示信息。
  • code定义错误的类型。

Spring Boot是从Spring发展而来的,所以自然支持Hibernate Validator和Spring Validation两种方式,默认使用的是Hibernate Validator组件。

2.数据校验

使用Hibernate Validator校验数据需要定义一个接收的数据模型,使用注解的形式描述字段校验的规则。下面以User对象为例演示如何使用Hibernate Validator校验数据。

2.1 JavaBean参数校验

Post请求参数较多时,可以在对应的数据模型(Java Bean)中进行数据校验,通过注解来指定字段校验的规则。下面以具体的实例来进行演示。首先,创建Java Bean实体类:

public class User {
    @NotBlank(message = "姓名不允许为空!")
    @Length(min = 2, max = 1,message = "姓名长度错误,姓名长度2-10!")
    private String name;

    @NotNull(message ="年龄不能为空!")
    @Min(18)
    private int age;

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

    @Pattern(regexp = "((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$", message = "手机号格式错误")
    private String phone;

    @Email(message ="邮箱格式错误")
    private String email;

    //省略get和set方法
}

在示例中,每个注解中的属性message是数据校验不通过时要给出的提示信息,如@Email(message=“邮件格式错误”),当邮件格式校验不通过时,提示邮件格式错误。然后,添加数据校验方法:

    @PostMapping(path ="/check")
    public String check(@RequestBody @Valid User user, BindingResult result) {
        String name = user.getName();
        if(result.hasErrors()) {
            List<ObjectError> list = result.getAllErrors();
            for (ObjectError error : list) {
                System.out.println(error.getCode() + "_" + error.getDefaultMessage());
            }
        }
        return name;
    }

在上面的示例中,在@RequestBody注解后面添加了@Valid注解,然后在后面添加了BindingResult返回验证结果,BindingResult是验证不通过时的结果集合。

注意,BindingResult必须跟在被校验参数之后,若被校验参数之后没有BindingResult对象,则会抛出BindException。

最后,运行验证。

启动项目,在postman中请求/user/check接口,后台输出了数据验证的结果:

Length-密码长度错误,密码长度6-20!
Min-最小不能小于18
Length-姓名长度错误,姓名长度2-10!

通过上面的输出可以看到,应用系统对传入的数据进行了校验,同时也返回了对应的数据校验结果。

2.2 URL参数校验

一般GET请求都是在URL中传入参数。对于这种情况,可以直接通过注解来指定参数的校验规则。下面通过实例进行演示。

@Validated
public class UserController {
    @RequestMapping("/query")
    public String query(@Length(min = 2, max = 1, message ="姓名长度错误,姓名长度2-10!")
                        @RequestParam(name = "name", required = true) String name,
                        @Min(value = 1, message = "年龄最小只能1")
                        @Max(value = 99, message = "年龄最大只能9")
                        @RequestParam(name = "age", required = true) int age) {
        System.out.println(name + " , " + age);
        return name + " , " + age;
    }
}

在上面的示例中,使用@Range、@Min、@Max等注解对URL中传入的参数进行校验。需要注意的是,使用@Valid注解是无效的,需要在方法所在的控制器上添加@Validated注解来使得验证生效。

2.3 JavaBean对象级联校验

对于JavaBean对象中的普通属性字段,我们可以直接使用注解进行数据校验,那如果是关联对象呢?其实也很简单,在属性上添加@Valid注解就可以作为属性对象的内部属性进行验证(验证User对象,可以验证UserDetail的字段)。示例代码如下:

public class User {
    @Size(min = 3, max = 5, message = "list的Size在[3,5]")
    private List<String> list;
    @NotNull
    @Valid
    private Demo3 demo3;
}

public class UserDetail {
    @Length(min = 5,max = 17,message = "length长度在[5,17]之间")
    private String extField;
}

在上面的示例中,在属性上添加@Valid就可以对User中的关联对象UserDetail的字段进行数据校验。

2.4 分组校验

在不同情况下,可能对JavaBean对象的数据校验规则有所不同,有时需要根据数据状态对JavaBean中的某些属性字段进行单独验证。这时就可以使用分组校验功能,即根据状态启用一组约束。Hibernate Validator的注解提供了groups参数,用于指定分组,如果没有指定groups参数,则默认属于javax.validation.groups.Default分组。

下面通过示例演示分组校验。首先,创建分组GroupA和GroupB,示例代码如下:

public interface GroupA {    
}
public interface GroupB {
}

在上面的示例中,我们定义了GroupA和GroupB两个接口作为两个校验规则的分组。然后,创建实体类Person,并在相关的字段中定义校验分组规则,示例代码如下:

public class User {
    @NotBlank(message ="userId不能为空",groups = {GroupA.class})
/**用户id*/
    private Integer userId;
    @NotBlank(message ="用户名不能为空",groups = {GroupA.class})
    /**用户id*/
    private String name;

    @Length(min = 30,max = 40,message = "必须在[30,40]",groups = {GroupB.class})
    @Length(min = 20,max = 30,message = "必须在[20,30]",groups = {GroupA.class})
    /**用户名*/
    private int age;
}

在上面的示例中,userName字段定义了GroupA和GroupB两个分组校验规则。GroupA的校验规则为年龄在20~30,GroupB的校验规则为年龄在30~40。最后,使用校验分组:

@RequestMapping("/save")
public String save(@RequestBody @Validated({GroupA.class, Default.class}) Person person, BindingResult result) {
    System.out.println(JSON.toJSONString(result.getAllErrors()));
return "success";

在上面的示例中,在@Validated注解中增加了{GroupA.class,Default.class}参数,表示对于定义了分组校验的字段使用GroupA校验规则,其他字段使用默认规则。

3.自定义校验

Hibernate Validator支持自定义校验规则。通过自定义校验规则,可以实现一些复杂、特殊的数据验证功能。下面通过示例演示如何创建和使用自定义验证规则。

3.1 声明一个自定义校验注解

首先,定义新的校验注解@CustomAgeValidator,示例代码如下:

    @Min(value = 18, message ="年龄最小不能小于18")
    @Max(value = 120, message ="年龄最大不能超过120")
    @Constraint(validatedBy = {}) //不指定校验器
    @Documented
    @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CustomAgeValidator {
        String message() default "年龄大小必须大于18并且小于123";
        Class<?>[] groups() default {};
        Class<? extends Payload>[] payload() default {};
    }

在上面的示例中,我们创建了CustomAgeValidator自定义注解,用于自定义年龄的数据校验规则。

3.2 使用自定义校验注解

创建自定义校验注解CustomAgeValidator之后,在User的age属性上使用自定义组合注解,示例代码如下:

@public class User {
    @NotBlank(message ="姓名不允许为空!")
    @Length(min = 2,max = 10,message ="姓名长度错误,姓名长度2-10!")
    private String name;
    @CustomAgeValidator
    private int age;
    @NotBlank(message ="地址不能为空!")
    private String address;
    @Pattern(regexp = "((13[-9])|(14[5,7,9])|(15([-3]][5-9]))|(166)(17[.1,3,5,6,7,8])l(18[0-9])I(19[8|9]))\\d{8}$", message ="手机号格式错误")
    private String phone;
    @Email(message ="邮箱格式错误")
    private String email;
    //省略get和set
}

在上面的示例中,我们在需要做特殊校验的age字段上添加@CustomAgeValidator自定义注解,这样age字段就会使用我们自定义的校验规则。

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

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

相关文章

mysql(三)用户权限管理

目录 前言 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、删除用户 前言 为什么要设置用户权限&#xff1f; MySQL设置用户管理权限的主要目的是为了确保数据库的安全性和数据的机密性。以下是一些原因&#xff1a; 1. 安全性&#xff1a;MySQL是一个开源的关系型…

多线程案例 | 单例模式、阻塞队列、定时器、线程池

多线程案例 1、案例一&#xff1a;线程安全的单例模式 单例模式 单例模式是设计模式的一种 什么是设计模式&#xff1f; 设计模式好比象棋中的 “棋谱”&#xff0c;红方当头炮&#xff0c;黑方马来跳&#xff0c;针对红方的一些走法&#xff0c;黑方应招的时候有一些固定的…

【C++初阶】:模板进阶

模板进阶 一.非类型模板参数二.模板的特化1.概念2.函数模板特化3.类的特化1.全特化2.偏特化 三.模板的分离编译 一.非类型模板参数 模板参数分类类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类…

Play 资产分发(Play Asset Delivery)

一、前言 Google Play发布应用&#xff0c;只支持上传aab格式文件。在之前&#xff0c;Google Play对上传apk文件限制大小不超过150MB&#xff0c;对于新的aab格式文件&#xff0c;也要求生成的目标apk不超过150MB&#xff08;GooglePlay后台使用bundletool生成apk文件&#xf…

虚拟机网络桥接,详细操作步骤,本地连接虚拟机

虚拟机网络桥接 文章目录 虚拟机网络桥接一&#xff0c;首先查看主机连接网络的网关二、打开虚拟机的worksation服务三、修改主机的VMnet8的IPV4属性四、修改虚拟机的workstation的虚拟网络五、修改VMnet8的IP,网关六、把虚拟机设置为桥接模式七、修改虚拟机的静态ip和对应的网…

JAVA面试总结-Redis篇章(三)——缓存雪崩

JAVA面试总结-Redis篇章&#xff08;三&#xff09;——缓存雪崩

测试开发之系统篇 - 常用系统命令

目录 前言&#xff1a; 查看占用端口的进程 Linux Windows 杀死进程 Linux Windows 按名称查看进程 命令行管道 后台运行服务 修改文件 Linux Mac 复制目录到远程 实时查看文件内容 查看正在运行的服务 查看服务状态 重启服务 查看内存状况 查看磁盘状况 …

基于MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化下评估及论文写作教程

详情点击链接&#xff1a;基于MAXENT模型的生物多样性生境模拟与保护优先区甄选、自然保护区布局优化及未来气候变化下评估中的应用及论文写作 一&#xff1a;生物多样性保护格局与自然保护区格局优化 1.我国生物多样性格局与分布&#xff1b; 2.我国自然保护区格局与分布&…

前端年度工作述职报告优秀

前端年度工作述职报告优秀篇1 尊敬的各位领导、各位同仁&#xff1a; 大家好!按照20__年度我公司就职人员工作评估的安排和要求&#xff0c;我认真剖析、总结了自己的工作情况&#xff0c;现将本人工作开展情况向各位领导、同仁做以汇报&#xff0c;有不妥之处&#xff0c;希…

注册外部的AudioPolicy,监听焦点变化

开始 AudioFocus分发流程 在上面分发流程分析中&#xff0c;最终是在MediaFocusControl中进行处理的&#xff0c;在requestAudioFocus​方法中可以看到在执行焦点栈逻辑时会先执行AudioPolicy相关逻辑&#xff0c; 因此我们试一试可不可以利用这一点&#xff0c;来注册外部的…

用于开漏模式和推拉模式的 4bit 双向电平转换器MS4554N/MS4554N1

MS4554N/MS4554N1 是一款双向电平转换器&#xff0c;可以应用在 混合电压的数字信号系统。其使用两个独立构架的电源供电&#xff0c; A 端供电电压范围是 1.65V 到 5.5V &#xff0c; B 端供电电压范围是 2.3V 到 5.5V 。可用在电源电压为 1.8V 、 2.5V 、 3.3V 和…

FPGA学习——按键消抖的两种实现方法

文章目录 一、按键消抖简介1.1、为什么要按键消抖 二、C4开发板原理图三、按键消抖源码3.1、方案一&#xff08;每当检测到下降沿便开始重新计数&#xff09;3.2、方案二&#xff08;检测到第一次下降沿后便开始计数&#xff09; 四、仿真代码及仿真波形图五、拓展&#xff1a;…

【金万维】使用天联高级版登录用友U8,文件输出操作。

【操作步骤】 1、通过天高客户端登录U8后&#xff0c;打开对应的报表或者列表&#xff08;以余额表为例&#xff09;。 2、点击“输出”按钮后&#xff0c;弹出“另存为”窗口&#xff0c; 注意&#xff1a;当前“保存在&#xff1a;桌面”这个路径为服务器的桌面&#xff0c;…

matlab 读取fig中的数据

1.使用命令打开fig open(文件名.fig) 2.查看图像包含的数据和属性 Location是原始的&#xff0c;Normal 可能是调整了顺序后的。

echarts制作多个纵轴的折线图

代码 <script type"text/javascript"> $(function (){var myChart echarts.init(document.getElementById(main));option {color: ["#9bbb59","#0B438B","#4141F1","#F81945","#4bacc6","#F89E19&q…

怎么把知识问答做成二维码?分享简单的二维码制作工具

现在无论是工厂的职工还是学校的学生&#xff0c;都会有各种各样的知识问答。传统的纸质知识问答&#xff0c;不仅浪费人力物力&#xff0c;还需要占用上班或是上学的时间来完成。为了方便大家使用&#xff0c;我们可以把知识问答做成二维码图片&#xff0c;随时随地手机扫一扫…

【代码随想录day20】二叉搜索树中的搜索

题目 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 思路 因为这里是二叉排序树&#xff0c;所以不用爆搜所有节点…

RTOS 低功耗设计原理及实现

RTOS 低功耗设计原理及实现 文章目录 RTOS 低功耗设计原理及实现&#x1f468;‍&#x1f3eb;前言&#x1f468;‍&#x1f52c;Tickless Idle Mode 的原理及实现&#x1f468;‍&#x1f680;Tickless Idle Mode 的软件设计原理&#x1f468;‍&#x1f4bb;Tickless Idle Mo…

超过443万人次观看|央媒聚焦全球吉商大会,实在智能携国产大模型TARS出席

据吉林新闻联播近期报道&#xff0c;第八届全球吉商大会、第二届吉林省校友人才促进吉林振兴发展大会在长春开幕。省委书记景俊海出席开幕式并讲话。省委副书记、省长胡玉亭主持开幕式。省政协主席朱国贤为“吉商突出贡献人物”颁奖。全国工商联副主席汪鸿雁致辞。开幕式全程进…

3.2.20:DTP与Datepicker实现日期的输入

【分享成果&#xff0c;随喜正能量】人生艰难自不必去回避&#xff0c;人生艰难说多了也是白说&#xff0c;为什么&#xff0c;解决不了问题&#xff0c;说了也还是那么难。。 我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高…