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

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注解自定义注解和处理类创建参数接收类&#xff0c;并增加字段注解接口中使用自测环节正常测试异常测试自定义全局异常监听扩展递归参数下valid不识别的坑前言 再项目开发中&#xff0c;针对前端传递的参数信息&#xf…...

c语言基础练习题详解

&#x1f49e;&#x1f49e; 1.C语言程序的基本单位是&#xff08;C&#xff09;。 A&#xff0e;程序行 B&#xff0e; 语句 C&#xff0e; 函数 D&#xff0e;字符 &#x1f49e;&#x1f49e; 2.已知各变量的类型说明如下&#xff1a; int m6,n,a,b; unsigned long w8;…...

C语言设计模式:实现简单工厂模式和工程创建

目录 一&#xff0c;设计模式概念引入 ① 什么是设计模式 ② 什么是类和对象 ③ 什么是工厂模式 二&#xff0c;C语言工厂模式的实现 ① 普通类和对象的代码实现 ② 工厂模式代码实现 ● cat.c ● dog.c ● person.c ● animal.h ● mainpro.c ● 完善mainpro.c …...

3.6日报

今天进行3.0信号整理工作 做官网后台技术文档 了解grpc gRPC是rpc框架中的一种&#xff0c;是rpc中的大哥 是一个高性能&#xff0c;开源和通用的RPC框架&#xff0c;基于Protobuf序列化协议开发&#xff0c;且支持众多开发语言。 面向服务端和协议端&#xff0c;基于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 基础(五)之 映射

目录前言一、映射&#xff08;Mapping&#xff09;简介二、动态映射&#xff08;Dynamic mapping&#xff09;1、动态字段映射1.1、日期检测1.1.1、禁用日期检测1.1.2、自定义检测到的日期格式1.2、数值检测2、动态模板三、显示映射&#xff08;Explicit mapping&#xff09;1、…...

【C语言督学训练营 第二天】C语言中的数据类型及标准输入输出

文章目录一、前言二、数据类型1.基本数据类型①.整形②.浮点型③.字符型2.高级数据类型3.数据分类①.常量②.变量三、标准输入输出1.scanf2.printf四、进制转换1.进制转换简介2.十进制转其他进制3.其他进制转换五、OJ网站的使用一、前言 王道2024考研408C语言督学营第二天&…...

重资产模式和物流网络将推动京东第四季度利润率增长

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 强劲的2022年第三季度财务业绩 2022年11月18日&#xff0c;京东&#xff08;JD&#xff09;公布了2022年第三季度财务业绩&#xff0c;净收入为2435亿元人民币&#xff0c;增长了11.4%。净服务收入为465亿元人民币&#xf…...

【新】EOS至MES的假捻报工数据导入-V2.0版本

假捻自动线的数据和MES没有进行对接,直接入库至EOS。 因此可信平台上缺少这部分的报工数据,需要把EOS的入库数据导出,整理成报工数据,导入到MES,然后通过定时任务集成到可信平台。 MES这边的报工数据整理,主要是添加订单明细ID,和完工单号。 订单明细ID(根据批次号和…...

python甜橙歌曲音乐网站平台源码

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;python音乐 获取完整源码源文件说明文档配置教程等 在虚拟环境下输入命令“python manage.py runserver”启动项目&#xff0c;启动成功后&#xff0c;访问“http://127.0.0.1:5000”进入甜橙音乐网首页&#xff0c;如图1所…...

docker imageID计算

Image ID是在本地由Docker根据镜像的描述文件计算的&#xff0c;并用于imagedb的目录名称 docker镜像id都保存在/var/lib/docker/image/overlay2/imagedb/content/sha256下面&#xff0c;都是一些以sha256sum计算文件内容得出的哈希值的文件。 #ls /var/lib/docker/image/ove…...

借助媛如意让ROS机器人turtlesim画出美丽的曲线-云课版本

首先安装并打开猿如意其次打开蓝桥云课ROS并加入课程在猿如意输入问题得到答案在蓝桥云课ROS验证如何通过turtlesim入门ROS机器人您可以通过以下步骤入门ROS机器人&#xff1a;安装ROS&#xff1a;您需要安装ROS&#xff0c;可以在ROS官网上找到安装指南。安装turtlesim&#x…...

小区业主入户安检小程序开发

小区业主入户安检小程序开发 可针对不同行业自定义安检项目&#xff0c;线下安检&#xff0c;线上留存&#xff08;安检拍照/录像&#xff09;&#xff0c;提高安检人员安检效率 功能特性&#xff0c;为你介绍小区入户安检系统的功能特性。 小区管理;后台可添加需要安检的小区…...

【C++知识点】异常处理

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4da;专栏地址&#xff1a;C/C知识点 &#x1f4e3;专栏定位&#xff1a;整理一下 C 相关的知识点&#xff0c;供大家学习参考~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;…...

【FATE联邦学习debug】 No module named ‘federatedml‘

直接pip install federatedml是无法找得到这个库的。 这个的原因是环境变量的事情&#xff0c;因为在部署文档中&#xff0c;本身提示我们要更新一些环境变量&#xff0c;如果不export那些变量&#xff0c;下面的fate_test其实也是无法测试成功的。 打开bin/init_env.sh&#x…...

【Git】P1 Git 基础

Git 基础Git 基本概念集中式版本控制工具 与 分布式版本控制工具Git 下载与安装Bash 初始设置创建本地仓库Git 三区概念一个简单的提交流程更改文件后再次提交git 实现版本切换查看提交日志设置 git 快捷键版本切换&#xff08;一&#xff09;版本切换&#xff08;二&#xff0…...

智能交通数据集Rope3D(仅限科研使用)

Rope3D Dataset 官网&#xff1a;https://thudair.baai.ac.cn/index &#xff01;&#xff01;&#xff01;如想要使用Rope3D数据集进行2D检测&#xff0c;最后有我们处理完的数据集链接。 &#xff01;&#xff01;&#xff01; 介绍&#xff1a; DAIR-V2X数据集是首个用于…...

Java虚拟机JVM-面试题

1、Java 虚拟机是如何捕获异常的&#xff1f; 答&#xff1a; 在编译生成的字节码中&#xff0c;每个方法都附带一个异常表。异常表中的每一个条目代表一个异常处理器&#xff0c;并且由 from 指针、to 指针、target 指针以及所捕获的异常类型构成。这些指针的值是字节码索引…...

详细的说说Redis的数据类型

Redis是一个开源的内存数据库&#xff0c;它可以用作缓存、消息代理、实时数据处理和许多其他用途。Redis是一个key-value存储系统&#xff0c;其中数据存储在内存中&#xff0c;并通过网络进行访问。与传统的关系型数据库不同&#xff0c;Redis支持多种数据结构&#xff0c;包…...

798.差分矩阵

输入一个 n行 m列的整数矩阵&#xff0c;再输入 q个操作&#xff0c;每个操作包含五个整数 x1,y1,x2,y2,c&#xff0c;其中 (x1,y1)和 (x2,y2) 表示一个子矩阵的左上角坐标和右下角坐标。每个操作都要将选中的子矩阵中的每个元素的值加上 c。 请你将进行完所有操作后的矩阵输出…...

算法题(回溯)

一、题目1、括号生成&#xff08;LC 22&#xff09;2、单词搜索&#xff08;LC 79&#xff09;二、题解1、括号生成&#xff08;LC 22&#xff09;&#xff08;1&#xff09;分析采用回溯的思想解决。递归方法包括 left、right、ans、path、n 五个核心参数&#xff0c;其中 lef…...

光纤链路故障排查:从指示灯误导到光功率测量的工程实践

1. 项目概述&#xff1a;一个关于“指示灯谎言”的工程教训在电子工程和测试测量领域&#xff0c;我们习惯于依赖设备上的指示灯——那些绿色、红色或琥珀色的小灯——来快速判断系统状态。它们是我们与复杂硬件对话的直观语言。然而&#xff0c;今天我想分享一个十多年前的真实…...

构建动态AI伦理评估工具链:从公平性、可解释性到全流程治理

1. 项目概述&#xff1a;为什么我们需要一个动态的AI伦理评估工具&#xff1f;在过去的几年里&#xff0c;我参与过不少AI项目的评审和落地&#xff0c;一个越来越强烈的感受是&#xff1a;大家对于“AI伦理”这四个字&#xff0c;已经从最初的“口号式”关注&#xff0c;变成了…...

边缘AI实战:从医疗到零售的系统级挑战与软硬件协同设计

1. 项目概述&#xff1a;当AI走出云端&#xff0c;走进现实“边缘AI”这个词&#xff0c;现在听起来可能已经不新鲜了&#xff0c;但真正把它从概念变成手边可用的工具&#xff0c;甚至是一个能独立决策的“小脑”&#xff0c;这个过程里踩过的坑、绕过的弯&#xff0c;可能比想…...

004、TinyML技术栈全景图:从模型到部署

004 TinyML技术栈全景图:从模型到部署 去年冬天调试一个智能门磁项目,板子是STM32L4,Flash只有256KB。模型在PC上跑F1值0.97,烧进去直接死机——不是推理结果不对,是内存分配直接溢出。我盯着map文件看了三个小时,最后发现是TensorFlow Lite Micro的arena大小设错了,多…...

【网络安全】什么是漏洞扫描?有哪些功能?

【网络安全】什么是漏洞扫描&#xff1f;有哪些功能&#xff1f; 一、什么是漏洞扫描&#xff1f; 漏洞扫描是指基于CVE、CNVD、CNNVD 等漏洞数据库&#xff0c;通过专用工具扫描手段对指定的远程或者本地的网络设备、主机、数据库、操作系统、中间件、业务系统等进行脆弱性评估…...

AI提示词工程实战:结构化系统与用户提示词提升AI工具效能

1. 项目概述&#xff1a;一个为AI工具提供高质量提示词的“弹药库”如果你和我一样&#xff0c;每天都在和各种AI工具打交道——从写代码的Cursor、ChatGPT&#xff0c;到画图的Midjourney、DALL-E&#xff0c;再到处理数据的Pandas AI——那你肯定遇到过这样的时刻&#xff1a…...

告别编译噩梦:在Ubuntu 22.04上为你的C++项目搞定Abseil依赖的三种方法

告别编译噩梦&#xff1a;在Ubuntu 22.04上为你的C项目搞定Abseil依赖的三种方法 在C项目的开发过程中&#xff0c;依赖管理一直是开发者面临的一大挑战。特别是对于现代C项目而言&#xff0c;如何高效、可靠地引入和管理第三方库&#xff0c;往往决定了项目的开发效率和最终质…...

Encaustic不是滤镜!揭秘热蜡媒介物理特性如何反向重构MJ提示词结构:材料科学×AIGC的跨学科实践

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;Encaustic不是滤镜&#xff01;——热蜡媒介的本质祛魅 Encaustic&#xff08;热蜡绘画&#xff09;常被误认为是数字图像处理中的一种“复古滤镜”&#xff0c;实则是一种拥有两千多年历史的实体绘画媒…...

研发交付管理:资源化与项目制的实践思考

说明&#xff08;阅读前&#xff09;&#xff1a;本文系 方法论层面的归纳&#xff0c;依据常见软件研发组织实践整理&#xff0c;不涉及任何特定企业的内部制度、人数或薪酬细节&#xff1b;文中角色名称&#xff08;如研发经理、项目发起人&#xff09;为 通用称谓&#xff0…...