当前位置: 首页 > news >正文

数据校验:Spring Validation

Spring Validation概述

在开发中,我们经常遇到参数校验的需求,比如用户注册的时候,要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式,我们会把校验的代码和真正的业务处理逻辑耦合在起,而且如果未来要新增一种校验逻辑也需要在修改多个地方。而spring validation允许通过注解的方式来定义对象校验规则,把校验和业务逻辑分离开,让代码编写更加方便。Spring Validation其实就是对Hibernate Validator进一步的封装,方便在Spring中使用。

在Spring中有多种校验的方式
第一种是通过实现org.springframework.validation.Validator接口,然后在代码中调用这个类

第二种是按照Bean Validation方式来进行校验,即通过注解的方式

第三种是基于方法实现校验

第四种实现自定义校验

 通过实现Validator接口实现

创建子模块 spring6-validator

引入依赖

    <dependencies><dependency><groupId>org.hibernate.validator</groupId><artifactId>hibernate-validator</artifactId><version>7.0.5.Final</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>jakarta.el</artifactId><version>4.0.1</version></dependency></dependencies>

创建实体类,定义属性,创建对应的set与get方法

public class Person {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

创建类,实现接口,实现接口的方法,编写校验逻辑

supports方法用来表示此校验用在哪个类型上
validate是设置校验逻辑的地点,其中ValidatorUtils,是Spring封装的校验工具类,帮助快速实现校验

public class PersonValidator implements Validator {@Overridepublic boolean supports(Class<?> clazz) {//supports方法用来表示此校验用在哪个类型上return Person.class.equals(clazz);}//校验规则@Overridepublic void validate(Object target, Errors errors) {//validate是设置校验逻辑的地点,其中ValidatorUtils,是Spring封装的校验工具类,帮助快速实现校验//name不能为空ValidationUtils.rejectIfEmpty(errors,"name","name.empty","name is null");//age 不能小于0 不能大于100Person p = (Person) target;if (p.getAge() < 0){errors.rejectValue("age","age.value.error","age < 0");} else if (p.getAge() > 200) {errors.rejectValue("age","age.value.old","age > 200");}}
}

完成测试

//校验测试
public class TestPerson {public static void main(String[] args) {//创建person对象Person person = new Person();//创建person对应databinderDataBinder binder = new DataBinder(person);//设置 校验器binder.setValidator(new PersonValidator());//调用方法执行校验binder.validate();//输出校验结果BindingResult result = binder.getBindingResult();System.out.println(result.getAllErrors());}
}

Bean Validation注解实现


使用Bean Validation校验方式,就是如何将Bean Validation需要使用的javax.validation.ValidatorFactoryjavax.validation.Validator注入到容器中。

spring默认有一个实现类LocalValidatorFactoryBean,它实现了上面Bean Validation中的接口,并且也实现了org.springframework.validation.Validator接口。


创建配置类ValidationConfig,配置LocalValidatorFactoryBean

@Configuration
@ComponentScan("com.yogurt.spring6.validator.two")
public class ValidationConfig {@Beanpublic LocalValidatorFactoryBean validator(){return new LocalValidatorFactoryBean();}
}

创建实体类,定义属性,创建对应的set与get方法,在属性上面使用注解设置校验规则

常用注解说明


@NotNull 限制必须不为null
@NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0

@NotBlank 只作用于字符串类型,字符串不为空,并且trim0后不为空串@DecimalMax(value) 限制必须为一个不大于指定值的数字

@DecimalMin(value) 限制必须为一个不小于指定值的数字

@Max(value) 限制必须为一个不大于指定值的数字

@Min(value)限制必须为一个不小于指定值的数字限制必须符合指定的正则表达式@Pattern(value)

@size(max,min) 限制字符长度必须在min到max之间

@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

public class User {@NotNullprivate String name;@Min(0)@Max(150)private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

 在属性上面使用注解设置校验规则

创建校验器

用原生:import jakarta.validation.Validator; 

@Service
public class MyValidation1 {@Autowiredprivate Validator validator;private boolean validatorByUserOne(User user){Set<ConstraintViolation<User>> validate = validator.validate(user);return validate.isEmpty();}
}

用spring框架中:import org.springframework.validation.Validator;

@Service
public class MyValidation2 {@Autowiredprivate Validator validator;public boolean validatorByUserTwo(User user){BindException bindException = new BindException(user, user.getName());validator.validate(user,bindException);return bindException.hasErrors();}
}

完成测试

原生测试:

    @Testpublic void testValidationOne(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation1 validation1 = context.getBean(MyValidation1.class);User user = new User();//user.setName("luck");//user.setAge(20);boolean message = validation1.validatorByUserOne(user);System.out.println(message);}

正常结果 

spring框架测试:

    @Testpublic void testValidationTwo(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation2 validation2 = context.getBean(MyValidation2.class);User user = new User();
//        user.setName("luck");
//        user.setAge(20);boolean message = validation2.validatorByUserTwo(user);System.out.println(message);}
}

报错:
java.lang.IllegalArgumentException: Object name must not be null

修改-->设置姓名和年龄:

    @Testpublic void testValidationTwo(){ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyValidation2 validation2 = context.getBean(MyValidation2.class);User user = new User();user.setName("luck");user.setAge(20);boolean message = validation2.validatorByUserTwo(user);System.out.println(message);}
}

基于方法实现校验 

 创建配置类ValidationConfig

@Configuration
@ComponentScan("com.yogurt.spring6.validator.three")
public class ValidationConfig {@Beanpublic MethodValidationPostProcessor validationPostProcessor(){return new MethodValidationPostProcessor();}
}

创建实体类,定义属性,创建对应的set与get方法,在属性上面使用注解设置校验规则

public class User {@NotNullprivate String name;@Min(0)@Max(150)private int age;@Pattern(regexp = "^1(3|4|5|7|8)\\d{9}$",message = "手机号码格式错误")@NotBlank(message = "手机号码不能为空")private String phone;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}
}

 在属性上面使用注解设置校验规则

创建校验器

@Service
@Validated
public class MyService {public String testMethod(@NotNull @Valid User user){return user.toString();}
}

 

完成测试

public class TestUser {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService service = context.getBean(MyService.class);User user = new User();//user.setName("lucy");//user.setPhone("15545451223");service.testMethod(user);}
}

报错:Exception in thread "main" jakarta.validation.ConstraintViolationException: testMethod.arg0.name: 不能为null, testMethod.arg0.phone: 手机号码不能为空

修改-->设置姓名和手机号:

public class TestUser {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(ValidationConfig.class);MyService service = context.getBean(MyService.class);User user = new User();user.setName("lucy");user.setPhone("15545451223");service.testMethod(user);}
}

相关文章:

数据校验:Spring Validation

Spring Validation概述 在开发中&#xff0c;我们经常遇到参数校验的需求&#xff0c;比如用户注册的时候&#xff0c;要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式&#xff0c;我们会把校验的代码和真正的业务处理逻辑耦…...

CSS怎么选择除了第一个子元素外的其余同级子元素

使用 CSS 的:not()伪类选择器和:nth-child()伪类选择器 要通过CSS的代码选择某一个元素的除了第一个子元素外的其余的跟第一个子元素同级的子元素&#xff0c;可以结合使用CSS的:not()伪类选择器和:nth-child()伪类选择器进行选择。大致的语法如下&#xff1a; .parent > …...

Mac下eclipse配置JDK

目录 一、配置JDK&#xff0c;需要电脑下载Java并且配置环境 (1)、左上角找到“Eclipse”-->“Preferences...”​ (2)、找到“Java”-->“Installde JREs”-->界面显示电脑所安安装的Java&#xff1b;若没有需要点击“Add”进行配置​ ①、选择“Standard VM”--&g…...

基于springboot实现体育场馆运营平台项目【项目源码】

基于springboot实现体育场馆运营管理系统演示 系统开发平台 在该数码论坛系统中&#xff0c;Eclipse能给用户提供更多的方便&#xff0c;其特点一是方便学习&#xff0c;方便快捷&#xff1b;二是有非常大的信息储存量&#xff0c;主要功能是用在对数据库中查询和编程。其功能…...

优雅的Java编程:将接口对象作为方法参数

theme: smartblue 目录 概述 在Java编程中&#xff0c;方法的参数传递方式通常是通过基本类型、对象引用或者集合等方式。然而&#xff0c;一种更加优雅且灵活的设计模式是将接口对象作为方法的参数。这种方式为我们带来了许多好处&#xff0c;包括降低耦合性、实现多态性和可…...

一文简单聊聊protobuf

目录 基本介绍 原理 同类对比 为什么要使用protobuf? 基本介绍 protobuf的全称是Protocol Buffer&#xff0c;是Google提供的一种数据序列化协议。Protocol Buffers 是一种轻便高效的结构化数据存储格式&#xff0c;可以用于结构化数据序列化&#xff0c;很适合做数据存储…...

Unity Meta Quest 一体机开发(五):手势抓取概述

文章目录 &#x1f4d5;教程说明&#x1f4d5; Oculus Integration 中的三种手势抓取方式⭐Hand Grab⭐Touch Hand Grab⭐Distance Hand Grab 此教程相关的详细教案&#xff0c;文档&#xff0c;思维导图和工程文件会放入 Seed XR 社区。这是一个高质量知识星球 XR 社区&#…...

传输层中的TCP和UPD协议

一)应用层协议简介:根据需求明确要传输的信息&#xff0c;明确要传输的数据格式&#xff1b; 应用层协议:这个协议&#xff0c;实际上是和程序员打交道最多的协议了 1)其它四层都是操作系统&#xff0c;驱动&#xff0c;硬件实现好了的&#xff0c;咱们是不需要管 2)应用层:当我…...

插入排序算法(C++版)

1、什么是插入排序 插入排序&#xff08;Insertion Sort&#xff09;是一种简单直观的排序算法&#xff0c;它的基本思想是将一个待排序的数组分为已排序和未排序两个部分&#xff0c;然后逐步将未排序的元素插入到已排序的部分&#xff0c;直到整个数组有序。 2、插入排序的…...

Tracking vs. No-Tracking Queries

学习链接 Tracking queries By default, queries that return entity types are tracking. A tracking query means any changes to entity instances are persisted by SaveChanges. var blog context.Blogs.SingleOrDefault(b > b.BlogId 1); blog.Rating 5; contex…...

Centos7安装frps实现内网穿透

前提 公网设备&#xff1a;云服务器1台&#xff0c;带公网IP 内网设备&#xff1a;linux、群晖、openwrt都可以 我的环境&#xff1a; 云服务器&#xff1a;centos7.9 内网&#xff1a;openwrt软路由 防火墙&&安全组 关闭云服务器的防火墙&#xff1a; 关闭防火墙…...

cryptopp Base64Encoder \n问题

1、问题&#xff1a; new Base64Encoder(new StringSink(out_base)) 调用库函数Base64Encoder进行base64加密后确认多出来了\n 2、原因 base64加密的问题, 由于base64一行不能超过76字符, 超过就会添加回车换行符(在Windows中是 \r\n , 在Linux中是 \n ) 3、解决 方法一、给定参…...

一种艺术风格的神经算法:总结与实现

一、说明 神经风格或神经转移允许以新的艺术风格再现给定的图像。在这里,我介绍了 Leon A. Gatys、Alexander S. Ecker 和 Matthias Bethge 提出的神经风格算法。该算法接收样式图像、内容图像和输入图像,输入图像可以是空的白色图像,也可以是内容图像的副本。因此,…...

【Mysql系列】Mysql基础篇

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

C++面试题之C++中的指针参数传递和引用参数传递

在C中&#xff0c;可以使用指针参数传递和引用参数传递来将参数传递给函数。这两种方法都可以修改函数外部的变量。 指针参数传递: 当使用指针参数传递时&#xff0c;函数接收一个指向变量的指针作为参数。在函数内部&#xff0c;通过解引用指针来访问和修改原始变量的值。这种…...

[Android]Unresolved reference: appcompat

问题 我创建了一个Kotlin class&#xff0c;然后导入并同步了依赖 implementation("androidx.appcompat:appcompat:1.6.1”)&#xff0c;但Class中还是提示报错还是提示Unresolved reference: appcompat 。 代码如下&#xff1a; package com.example.gatestdemol imp…...

网络运维Day14

监控概述 监控的目的 报告系统运行状况每一部分必须同时监控内容包括吞吐量、反应时间、使用率等提前发现问题进行服务器性能调整前&#xff0c;知道调整什么找出系统的瓶颈在什么地方 监控的资源类别 公开数据 Web、FTP、SSH、数据库等应用服务TCP或UDP端口 私有数据 CPU、内…...

Mac常用软件安装

brew安装 brew 是从下载源码解压然后 ./configure && make install &#xff0c;同时会包含相关依存库。并自动配置好各种环境变量&#xff0c;而且易于卸载。 这个对程序员来说简直是福音&#xff0c;简单的指令&#xff0c;就能快速安装和升级本地的各种开发环境。 …...

node 文件上传操作(前端 form表单上传 formData上传 后端 node 使用express+multer)

目录 前端form表单上传formData上传 后端 node 使用expressmulter 前端 form表单上传 <h1>个人信息</h1><form action"http://localhost:3000/api/sendFile" method"post" enctype"multipart/form-data"><label for"…...

容器数据卷+MYSQL实战

什么是容器数据卷&#xff1f; 让我们回忆一下docker理念&#xff1a; 就是将应用和环境打包成一个镜像 数据&#xff1f; 如果数据都在容器中&#xff0c;那么我们删除容器&#xff0c;数据就会丢失 &#xff01;需求&#xff1a;数据持久化就完美了 对于MYSQL&#xff0…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...