Springboot——@valid 做字段校验和自定义注解
文章目录
- 前言
- 注意实现
- 测试环境
- 验证自带的注解
- 自定义valid注解
- 自定义注解和处理类
- 创建参数接收类,并增加字段注解
- 接口中使用
- 自测环节
- 正常测试
- 异常测试
- 自定义全局异常监听
- 扩展
- 递归参数下valid不识别的坑
前言
再项目开发中,针对前端传递的参数信息,有些接口中需要写大量的if
判断,导致代码臃肿,不够优雅。
此时,可以使用@Valid
实现基本的字段校验。
注意实现
- springboot 2.3之前 ,直接进行开发即可,无需引用额外的依赖
集成在spring-boot-starter-web
中。 - springboot 2.3之后 需要额外引入
spring-boot-starter-validation
依赖信息
测试环境
springboot 2.1.4
如果你的springboot版本高于 2.3
,需要额外引入下列依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
验证自带的注解
验证自带的注解,以及实现原理,可以移步到我的另一篇博客中,本篇博客不做过多的阐述。
做一个优雅的接口
自定义valid注解
官方提供的一些常用的注解,有时候并不能适合所有的开发需求。此时可以采取自定义valid
的方式,实现其应有的功能。
自定义注解和处理类
创建一个自定义的注解
检查排序号是否输入,以及是否满足要求。
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Constraint(validatedBy = POrderParse.class) // 注解对应的处理类
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface POrder {// 默认提示语句String message() default "排序号不允许为空,且只允许是1到20的数字!";// 默认校验正则表达式String regexp() default "^([1-9])|([1]\\d)|20$";Class<?>[] groups() default { };Class<? extends Payload>[] payload() default { };}
定义注解后,还需要定义其指定的处理类
,如下所示:
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorContextImpl;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;@Component
public class POrderParse implements ConstraintValidator<POrder,Object> {@Overridepublic void initialize(POrder constraintAnnotation) {System.out.println("my para order validator init");}@Overridepublic boolean isValid(Object value, ConstraintValidatorContext context) {// 校验逻辑ConstraintValidatorContextImpl con = (ConstraintValidatorContextImpl) context;// 获取注解中的属性值Map<String, Object> maps = con.getConstraintDescriptor().getAttributes();// 获取设置的或者默认的正则表达式String regexp = (String) maps.get("regexp");// 获取数据值String param = String.valueOf(value);// 正则判断Pattern regexpVo = Pattern.compile(regexp);Matcher matcher = regexpVo.matcher(param);return matcher.matches();}
}
创建参数接收类,并增加字段注解
import cn.xj.bi.volid.MyPhone;
import cn.xj.bi.volid.POrder;
import lombok.Data;@Data
public class User {@POrderprivate Integer order;
}
接口中使用
创建一个测试接口,进行应用测试。
需要使用到
@Valid
注解标识
@RestController
@RequestMapping("/test1")
@Api(tags = "测试")
public class TestController {@PostMapping("/demo4")@ApiOperation(value = "demo4")public CommonResult<String> test4(@RequestBody @Valid User user){return CommonResult.success("6666");}
)
自测环节
启动项目,进入swagger进行请求测试。
正常测试
传递满足正则要求
的值,查看返回结果信息。
{"order": 10
}
异常测试
参数中传递一个不满足正则
表达式的值,观察返回信息。
{"order": 0
}
自定义全局异常监听
每次返回这样的报错信息不够直观,此时可以自定义全局异常监听,如下所示:
import cn.xj.bi.vo.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.Objects;@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(MethodArgumentNotValidException.class)public CommonResult handleScopeFiledException(MethodArgumentNotValidException e) {log.error("字段合法性校验异常:[{}]", e.getMessage());// getFieldError() 和 getDefaultMessage() 的区别return CommonResult.error( Objects.requireNonNull(e.getBindingResult().getFieldError()).getDefaultMessage(), null);}
}
重启项目,再次异常测试:
扩展
递归参数下valid不识别的坑
递归参数的意思就是接收对象是一个类,假设是DataScope
,但是在这个接收类中,还有一个List<User>
这个参数变量,并且User
中依旧还含有需要valid
校验的字段属性。
再自定义一个valid注解,如下所示:
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Constraint(validatedBy = {MyPhoneValidtor.class})
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyPhone {String message();Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};}
valid注解具体处理类:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;public class MyPhoneValidtor implements ConstraintValidator<MyPhone,Object> {@Overridepublic boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {System.out.println("校验");// 故意返回false,触发异常return false;}
}
然后再请求参数接收对象中,定义如下格式:
import cn.xj.bi.volid.POrder;
import lombok.Data;@Data
public class User {@POrderprivate Integer order;private Address address;
}
import cn.xj.bi.volid.MyPhone;
import lombok.Data;
import java.io.Serializable;@Data
public class Address implements Serializable {@MyPhone(message = "这只是一个测试")private String phoneNum;
}
重启项目,传递正常的 order
值,观察Address 类中的 phoneNum
是否触发valid校验。
{"order": 10,"address":{"phoneNum":""}
}
发现并未触发对应的valid校验。
解决方式很简单,没有触发说明注解无效,接口中定义@Valid User
是对user对象进行valid处理,但对象类型的并不在列,只需要在对象类型的变量上增加@Valid
注解即可。
import cn.xj.bi.volid.POrder;
import lombok.Data;import javax.validation.Valid;@Data
public class User {@POrderprivate Integer order;@Valid // 迭代validprivate Address address;
}
重启项目,继续按照上面的传参,观察响应信息。
相关文章:
Springboot——@valid 做字段校验和自定义注解
文章目录前言注意实现测试环境验证自带的注解自定义valid注解自定义注解和处理类创建参数接收类,并增加字段注解接口中使用自测环节正常测试异常测试自定义全局异常监听扩展递归参数下valid不识别的坑前言 再项目开发中,针对前端传递的参数信息…...
c语言基础练习题详解
💞💞 1.C语言程序的基本单位是(C)。 A.程序行 B. 语句 C. 函数 D.字符 💞💞 2.已知各变量的类型说明如下: int m6,n,a,b; unsigned long w8;…...
C语言设计模式:实现简单工厂模式和工程创建
目录 一,设计模式概念引入 ① 什么是设计模式 ② 什么是类和对象 ③ 什么是工厂模式 二,C语言工厂模式的实现 ① 普通类和对象的代码实现 ② 工厂模式代码实现 ● cat.c ● dog.c ● person.c ● animal.h ● mainpro.c ● 完善mainpro.c …...
3.6日报
今天进行3.0信号整理工作 做官网后台技术文档 了解grpc gRPC是rpc框架中的一种,是rpc中的大哥 是一个高性能,开源和通用的RPC框架,基于Protobuf序列化协议开发,且支持众多开发语言。 面向服务端和协议端,基于http…...
中文代码88
PK 嘚釦 docProps/PK 嘚釦|,g z docProps/app.xml漅AN??駠(髂v诖m岼侸 魣,g踃$秂D廋Qvf漶x莗笳w?:瘜^?俍欶辇2}?睧汎 t#:?效7治XtA鏊?羄鈋嫿饄攗Tv契"D桷撵vJ鉂?闌 Jg??浱?樱沲gic鋹峡?sū窛葻?]迾?9卑{艏 rk\?洺萹啰N?W??2&quo…...
ElasticSearch 基础(五)之 映射
目录前言一、映射(Mapping)简介二、动态映射(Dynamic mapping)1、动态字段映射1.1、日期检测1.1.1、禁用日期检测1.1.2、自定义检测到的日期格式1.2、数值检测2、动态模板三、显示映射(Explicit mapping)1、…...
【C语言督学训练营 第二天】C语言中的数据类型及标准输入输出
文章目录一、前言二、数据类型1.基本数据类型①.整形②.浮点型③.字符型2.高级数据类型3.数据分类①.常量②.变量三、标准输入输出1.scanf2.printf四、进制转换1.进制转换简介2.十进制转其他进制3.其他进制转换五、OJ网站的使用一、前言 王道2024考研408C语言督学营第二天&…...
重资产模式和物流网络将推动京东第四季度利润率增长
来源:猛兽财经 作者:猛兽财经 强劲的2022年第三季度财务业绩 2022年11月18日,京东(JD)公布了2022年第三季度财务业绩,净收入为2435亿元人民币,增长了11.4%。净服务收入为465亿元人民币…...
【新】EOS至MES的假捻报工数据导入-V2.0版本
假捻自动线的数据和MES没有进行对接,直接入库至EOS。 因此可信平台上缺少这部分的报工数据,需要把EOS的入库数据导出,整理成报工数据,导入到MES,然后通过定时任务集成到可信平台。 MES这边的报工数据整理,主要是添加订单明细ID,和完工单号。 订单明细ID(根据批次号和…...
python甜橙歌曲音乐网站平台源码
wx供重浩:创享日记 对话框发送:python音乐 获取完整源码源文件说明文档配置教程等 在虚拟环境下输入命令“python manage.py runserver”启动项目,启动成功后,访问“http://127.0.0.1:5000”进入甜橙音乐网首页,如图1所…...
docker imageID计算
Image ID是在本地由Docker根据镜像的描述文件计算的,并用于imagedb的目录名称 docker镜像id都保存在/var/lib/docker/image/overlay2/imagedb/content/sha256下面,都是一些以sha256sum计算文件内容得出的哈希值的文件。 #ls /var/lib/docker/image/ove…...
借助媛如意让ROS机器人turtlesim画出美丽的曲线-云课版本
首先安装并打开猿如意其次打开蓝桥云课ROS并加入课程在猿如意输入问题得到答案在蓝桥云课ROS验证如何通过turtlesim入门ROS机器人您可以通过以下步骤入门ROS机器人:安装ROS:您需要安装ROS,可以在ROS官网上找到安装指南。安装turtlesim&#x…...
小区业主入户安检小程序开发
小区业主入户安检小程序开发 可针对不同行业自定义安检项目,线下安检,线上留存(安检拍照/录像),提高安检人员安检效率 功能特性,为你介绍小区入户安检系统的功能特性。 小区管理;后台可添加需要安检的小区…...
【C++知识点】异常处理
✍个人博客:https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 📚专栏地址:C/C知识点 📣专栏定位:整理一下 C 相关的知识点,供大家学习参考~ ❤️如果有收获的话,欢迎点赞👍…...
【FATE联邦学习debug】 No module named ‘federatedml‘
直接pip install federatedml是无法找得到这个库的。 这个的原因是环境变量的事情,因为在部署文档中,本身提示我们要更新一些环境变量,如果不export那些变量,下面的fate_test其实也是无法测试成功的。 打开bin/init_env.sh&#x…...
【Git】P1 Git 基础
Git 基础Git 基本概念集中式版本控制工具 与 分布式版本控制工具Git 下载与安装Bash 初始设置创建本地仓库Git 三区概念一个简单的提交流程更改文件后再次提交git 实现版本切换查看提交日志设置 git 快捷键版本切换(一)版本切换(二࿰…...
智能交通数据集Rope3D(仅限科研使用)
Rope3D Dataset 官网:https://thudair.baai.ac.cn/index !!!如想要使用Rope3D数据集进行2D检测,最后有我们处理完的数据集链接。 !!! 介绍: DAIR-V2X数据集是首个用于…...
Java虚拟机JVM-面试题
1、Java 虚拟机是如何捕获异常的? 答: 在编译生成的字节码中,每个方法都附带一个异常表。异常表中的每一个条目代表一个异常处理器,并且由 from 指针、to 指针、target 指针以及所捕获的异常类型构成。这些指针的值是字节码索引…...
详细的说说Redis的数据类型
Redis是一个开源的内存数据库,它可以用作缓存、消息代理、实时数据处理和许多其他用途。Redis是一个key-value存储系统,其中数据存储在内存中,并通过网络进行访问。与传统的关系型数据库不同,Redis支持多种数据结构,包…...
798.差分矩阵
输入一个 n行 m列的整数矩阵,再输入 q个操作,每个操作包含五个整数 x1,y1,x2,y2,c,其中 (x1,y1)和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。每个操作都要将选中的子矩阵中的每个元素的值加上 c。 请你将进行完所有操作后的矩阵输出…...
InfluxDB 2 介绍与使用 flux查询 数据可视化
一、关键概念 相比V1 移除了database 和 RP,增加了bucket。 V2具有以下几个概念: timestamp、field key、field value、field set、tag key、tag value、tag set、measurement、series、point、bucket、bucket schema、organization 新增的概念&…...
Qt QTreeView简单使用
QT-QTreeView使用方法 QTreeView: 用于显示树状结构数据,适用于树状结构数据的操作。 一、初始化 利用QStandardlternModel来初始化数据,标准的基于项数据的数据模型类, 每个项数据可以是任何数据类型。 // 初始化model QStandardItem…...
Wannacrypt蠕虫老树开花?又见Wannacrypt
Wannacrypt蠕虫是一个在2017年就出现的远古毒株,其利用永恒之蓝漏洞降维打击用户服务器,而后进行扩散勒索,曾经一度风靡全球,可谓是闻者伤心,听着落泪,因为这玩意解密是不可能 解密的。 而2023年的今天&am…...
结合基于规则和机器学习的方法构建强大的混合系统
经过这些年的发展,我们都确信ML即使不能表现得更好,至少也可以在几乎所有地方与前ML时代的解决方案相匹配。比如说一些规则约束,我们都会想到能否把它们替换为基于树的ml模型。但是世界并不总是黑白分明的,虽然机器学习在解决问题…...
Spring Security OAuth2实现多用户类型认证、刷新Token
原本的OAuth2登录支持用户名密码登录,现在还想支持另外用id号码和密码登录。但是OAuth2默认提供的UserDetailsService只允许传入一个参数:想要实现多种用户登录,是不是可以考虑loadUserByUsername方法携带多个参数呢?接下来记录一…...
云计算介绍,让你更了解云计算
同学们好! 第一次接触IT行业吗?没关系,看完这篇文章肯定会让你不再陌生。给自己几分钟时间,认真看完哦! 1、不知道什么是云计算? 网络计算云计算 官方定义是:通过网络提供可伸缩的分布式计算…...
阿里大佬翻遍全网Java面试文章,总结出这份1658页文档,GitHub收获25K+点赞
就目前大环境来看,跳槽成功的难度比往年高很多。一个明显的感受:今年的面试,无论一面还是二面,都很考验Java程序员的技术功底。这不又到了面试跳槽的黄金段,成功升职加薪,不成功饱受打击。当然也要注意&…...
【JDK1.8 新特性】Lambda表达式
1. 什么是Lambda表达式? Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达…...
【Vue.js】Vuex核心概念
文章目录全局状态管理模式Vuexvuex是什么?什么是“状态管理模式”?vuex的应用场景Vuex安装开始核心概念一、State1、单一状态树2、在 Vue 组件中获得 Vuex 状态3、mapState辅助函数二、Getter三、Mutation1、提交载荷(Payload)2、…...
react router零基础使用教程
安装既然学习 react router 就免不了运行 react安装 reactnpx create-react-app my-appcd my-appnpm start安装 react routernpm install react-router-dom如果一切正常,就让我们打开 index.js 文件。配置路由引入 react-router-dom 的 RouterProviderimport {Route…...
怎么做用户调研网站/网络营销系统
CENTOS的备份和恢复其实非常简单,我们只要把全部文件用TAR打包就行,下次需要恢复的适合再解压开覆盖就可以了下面详解CENTOS备份和还原的过程tar打包命令的特点:1、保留权限2、适合备份整个目录3、可以选择不同的压缩方式4、如果选择不压缩还…...
金华建设监理协会网站/百度推广怎么联系
\documentclass{ctexart}\usepackage{enumerate}\begin{document}\begin{enumerate}[{case}1]\item new\item new\item new\end{enumerate}\end{document}转载于:https://www.cnblogs.com/zhangzujin/p/5574730.html...
郑州网站seo技术/盐城网站优化
ADSL线路上传与下载速度之间关系ADSL上传速度对下载的影响--------------------------------------------------------------------------------------TCP/IP规定,每一个封包,都需要有acknowledge讯息的回传,也就是说,传输的资料&…...
如何开展网站推广/seo查询是什么
官网:https://ustbhuangyi.github.io/vue-analysis/...
用什么框架做网站快/热门推广平台
90.1 演示环境介绍 实现流程: CM和CDH版本:5.13.1CDSW和CDH集群操作系统为RedHat:7.2Nginx服务器:RedHat6.4Livy版本:0.4Nginx版本:1.8.6 90.2 操作演示 1.安装DNS服务并配置泛域名解析 该DNS服务主要…...
淘宝不能发布网站源码做商品/无代码免费web开发平台
1xx消息 这一类型的状态码,代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。由于HTTP/1.0协议中没有定义任何1xx状态码,所以除非在某些试验条件下,服…...