Java自定义校验注解实现List、set集合字段唯一性校验
文章目录
- 一: 使用场景
- 二: 定义FieldUniqueValid注解
- 2.1 @FieldUniqueValid
- 2.2 注解说明
- 2.3 @Constraint 注解介绍
- 2.4 @FieldUniqueValid注解使用
- 三:自定义FieldUniqueValidator校验类
- 3.1 实现ConstraintValidator
- 3.2 重写initialize方法
- 3.3 重写isValid方法
- 3.4 获取list集合重复数据的下标
- 3.5 思路
- 3.6 测试
- 3.6.1 前端传递参数,需要进行唯一性校验的字段
- 3.6.2 message提示
一: 使用场景
在开发过程中,前端给后端传递集合,并且需要保证集合的实体类中的某些字段必须是惟一的,不能重复。
传递的集合:
private List<User> userInfoList;
集合对应的实体类:
@Data
public class User {private int id;private String name;private String card;}
如果我们要保证传递的name或者card必须是唯一的,不能重复,应该如何实现呢,此时可以通过自定义注解的方式实现。
二: 定义FieldUniqueValid注解
2.1 @FieldUniqueValid
/*** 该注解用于校验List集合实体类当中的某些字段的唯一性* <p>* 条件表达式支持使用"$parent."获取父节点属性(实体内不能使用除List集合外的其他集合类型,例如Set等)* <ul>* <li>标记在字段上:用于指定单个或多个字段,fields需填写</li>* </ul>* @author ikun* @date 2023.07.27*/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FieldUniqueValidator.class)
public @interface FieldUniqueValid {//需要进行唯一校验的字段String[] fieldsCode() default{};String[] fieldsName() default{};String message() default "[fieldName]列[index]行数据重复";//不能有默认值,报错:contains Constraint annotation, but the groups parameter default value is not the empty arrayClass<?>[] groups() default {};//在那种组中使用Class<? extends Payload>[] payload() default {};
}
2.2 注解说明
@Documented
@Document 是 java 在生成文档,是否显示注解的开关。
@Target(ElementType.FIELD)
ElementType.FIELD:该注解只能声明在一个类的字段前。
2.3 @Constraint 注解介绍
@Constraint注解是Java Bean Validation框架中的一个注解,用于自定义约束注解,即自定义校验规则。
通过在自定义注解上添加@Constraint注解,可以将该注解标记为一个自定义约束注解。同时,需要指定一个实现了ConstraintValidator接口的验证器类,用于验证该注解所标记的字段或参数是否符合自定义的校验规则。
@Constraint注解有以下属性:
-
validatedBy:用于指定实现了ConstraintValidator接口的验证器类。该属性的值是一个Class对象数组,可以指定多个验证器类。
-
message:用于指定当校验失败时,所返回的错误信息。可以使用占位符{},在校验器中使用具体的参数替换。
-
groups:用于指定分组,即根据不同的分组应用不同的校验规则。
-
payload:用于指定元数据,即可以通过该属性传递一些额外的验证信息。
使用@Constraint注解,可以通过自定义注解的方式,为字段或参数添加自定义的校验规则,并实现校验逻辑。这样,在进行参数校验时,可以方便地通过注解的方式来调用自定义的校验规则。
2.4 @FieldUniqueValid注解使用
@FieldUniqueValid(fieldsCode = {"name,card"}, fieldsName = {"姓名,身份证号"})
private List<User> userInfoList;
- fieldsCode :需要校验的字段
- fieldsName :校验字段对应的名称
三:自定义FieldUniqueValidator校验类
@Slf4j
public class FieldUniqueValidator implements ConstraintValidator<FieldUniqueValid, Iterable<?>> {private String[] fieldsCode;private String[] fieldsName;/*** 数据有重复的字段名称*/private static final String FIELD_NAME= "[fieldName]";/*** 相同元素下标集合*/private static final String INDEX = "[index]";/*** 初始化参数* @param constraintAnnotation 注解的值*/@Overridepublic void initialize(FieldUniqueValid constraintAnnotation) {fieldsCode = constraintAnnotation.fieldsCode();fieldsName = constraintAnnotation.fieldsName();}@Overridepublic boolean isValid(Iterable<?> value, ConstraintValidatorContext context) {//如果没有配置校验字段信息,则直接通过if(fieldsCode.length == 0 && fieldsName.length == 0){return true;}if(fieldsCode.length != fieldsName.length){throw new RuntimeException("@FieldUniqueValid注解所对应的fieldsCode和fieldsName无法相互映射");}if(value == null){throw new RuntimeException("@FieldUniqueValid注解所在的集合为空,无法判断");}for (int i = 0; i < fieldsCode.length; i++) {List<Object> list = new ArrayList<>();Iterator<?> iterator = value.iterator();long index;for (index = 0; iterator.hasNext(); index++) {Object fieldValue = null;try {//forceAccess = true,属性是私有的,需要设置为true打开权限fieldValue = FieldUtils.readField(iterator.next(),fieldsCode[i],true);} catch (IllegalAccessException e) {log.error(fieldsName[i] + "转化失败,无法进行校验", e);}list.add(fieldValue);}//去重后的总数long count = list.stream().distinct().count();//去重之前和去重以后进行比较if(count < index){//返回重复元素下标集合String sameIndex = getListSameIndex(list);String defaultConstraintViolation = context.getDefaultConstraintMessageTemplate();context.disableDefaultConstraintViolation();String convertedConstraintViolation = defaultConstraintViolation.replace(FIELD_NAME, fieldsName[i]).replace(INDEX, sameIndex);context.buildConstraintViolationWithTemplate(convertedConstraintViolation).addConstraintViolation();return false;}}return true;}}
3.1 实现ConstraintValidator
ConstraintValidator<FieldUniqueValid, Iterable<?>>:
- FieldUniqueValid:需要校验的注解,就是我们自定义的
- Iterable<?>:前端传递list的类型,此时用Iterable是因为数据支持list和set集合
3.2 重写initialize方法
可以从onstraintAnnotation参数中获取fieldsCode、fieldsName里面的参数。主要作用就是将注解的参数进行初始化
3.3 重写isValid方法
Iterable<?> value, ConstraintValidatorContext context
- value:可以获取到传递的集合数据
- context:获取注解上的message信息
3.4 获取list集合重复数据的下标
/*** 集合【List】找出list中重复元素的下标(显示下标所在位置)* @param list*/public static String getListSameIndex(List<?> list){List<Object> same = new ArrayList<>();List<?> collect = list.stream().distinct().collect(Collectors.toList());if(collect.size() == list.size()){return null;}StringBuilder sb = new StringBuilder();for (int i = 0; i <collect.size(); i++) {for (int j = 0; j < list.size(); j++) {if (list.get(j).equals(collect.get(i))){same.add(j+1);}}if (same.size() > 1){sb.append(same).append("、");}same.clear();}return sb.substring(0, sb.toString().lastIndexOf("、"));}
3.5 思路
首先获取到集合的数据,然后通过反射,用循环遍历获取到name字段的list数据,然后去重。将去重前后的list进行比较。如果长度变化了则说明有重复数据。此时返回false。然后我们我们通过getListSameIndex方法获取到list重复数据的下标然后替换[index]。
3.6 测试
3.6.1 前端传递参数,需要进行唯一性校验的字段

3.6.2 message提示

相关文章:
Java自定义校验注解实现List、set集合字段唯一性校验
文章目录 一: 使用场景二: 定义FieldUniqueValid注解2.1 FieldUniqueValid2.2 注解说明2.3 Constraint 注解介绍2.4 FieldUniqueValid注解使用 三:自定义FieldUniqueValidator校验类3.1 实现ConstraintValidator3.2 重写initialize方法3.3 重…...
xiaoweirobot.chat
目录 1 xiaoweirobot.chat 1.1 DetailList 2 HttpData 2.1 doInBackground 2.2 onPostExecute xiaoweirobot.chatpackage com.shrimp.xiaoweirobot.chat; DetailList <...
【无公网IP】本地电脑搭建个人博客网站(并发布公网访问 )和web服务器
【无公网IP】本地电脑搭建个人博客网站(并发布公网访问 )和web服务器 文章目录 【无公网IP】本地电脑搭建个人博客网站(并发布公网访问 )和web服务器前言1. 安装套件软件2. 创建网页运行环境 指定网页输出的端口号3. 让WordPress在…...
SpringCloud(29):Nacos简介
1 什么是配置中心 1.1 什么是配置 应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。 配置主要有以下几个特点: 配置是独立于程序的只读变量 …...
freeBSD - 笔记
1 介绍 FreeBSD: FreeBSD是由FreeBSD项目团队开发的,最早可以追溯到1993年。它专注于性能、稳定性和可靠性,并在服务器和高性能计算环境中广泛使用。FreeBSD有着强大的网络性能和高度优化的TCP/IP协议栈,因此在网络服务器领域表…...
【Linux】网络基础——宏观认识计算机网络
1 计算机网络背景 网络发展 独立模式: 计算机之间相互独立; 一开始,计算机发明出来之后,一台计算机处理完的数据,数据会保存在软盘(物理),通过人之间的相互通信,把计算机A处理完的数据存储到软…...
数字人现身大运会,怎么以动作捕捉技术助推运动与文博相结合
中国移动动感地带数字人橙络络,作为数智体验官以元宇宙的视角,带领观众沉浸式体验大运会,以极具科技和未来的数字人,对外传递大运青春风采,并且数字人橙络络还对大运会的赛事、活动进行了科普、讲解以及表演当地特色才…...
WSL安装
WSL安装 1.Microsoft store 安装 1.1 启动WSL功能 在【程序和功能 -> 启用或关闭 Windows 功能】中勾选【适用于 Linux 的 Windows 子系统】 1.2 Store中下载安装 在 Microsoft Store 中下载并安装需要的 Linux 发行版 2.不使用Store安装WSL 注:1.1也要…...
MongoDB 入门
1.1 数据库管理系统 在了解MongoDB之前需要先了解先数据库管理系统 1.1.1 什么是数据? 数据(英语:data),是指未经过处理的原始记录。 一般而言,数据缺乏组织及分类,无法明确的表达事物代表的意…...
使用uni-app的uniCloud 云数据库入门:实现一个简单的增删改查
官方云数据库文档 前置步骤使用uni-app新建一个uniCloud项目 [外链图片转存失败,源站可能有防盗官方云数据库文档]!链机制,建议将()https://uniapp.dcloud.net.cn/uniCloud/hellodb.html)] 新建表 这里我加了几个测试字段 createTime、remark、money // 文档教程: https://un…...
【MATLAB第64期】【保姆级教程】基于MATLAB的SOBOL全局敏感性分析模型运用(含无目标函数,考虑代理模型)
【MATLAB第64期】【保姆级教程】基于MATLAB的SOBOL全局敏感性分析模型运用(含无目标函数,考虑代理模型) 版本更新: 2023/8/5: 1.因BP作为代理模型不稳定,经过测试,libsvm比rf /bp 效果稳定且精…...
Python web实战之Django用户认证详解
关键词: Python Web 开发、Django、用户认证、实战案例 概要 今天来探讨一下 Django 的用户认证吧!在这篇文章中,我将为大家带来一些有关 Django 用户认证的最佳实践。 1. Django 用户认证 在开发 Web 应用程序时,用户认证是一个…...
每天五分钟机器学习:梯度下降算法和正规方程的比较
本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…...
生信学院|08月18日《基于Flow Simulation的冷链运输产品案例》
课程主题:基于Flow Simulation的冷链运输产品案例 课程时间:2023年08月18日 14:00-14:30 主讲人:江流洋 生信科技 CAE专家 1、达索仿真方案介绍 2、项目介绍 3、案例分析 请安装腾讯会议客户端或APP,微信扫描海报中的二维码…...
不可错过的家装服务预约小程序商城开发指南
在当今社会,家装行业发展迅速,越来越多的人开始寻求专业的家装预约和咨询服务。对于不懂技术的新手来说,创建一个自己的家装预约咨询平台可能听起来很困难,但实际上通过一些第三方制作平台和工具,这个过程可以变得简单…...
任务 13、MidJourney种子激发极致创作,绘制震撼连贯画作
13.1 任务概述 通过本次实验任务,学员将深入了解Midjourney种子的概念和重要性,以及种子对生成图像的影响。他们将学会在Midjourney平台中设置种子值并调整其参数,以达到所需的效果。此外,任务还详细介绍了Midjourney V4.0版本中…...
IAR开发环境的安装、配置和新建STM32工程模板
IAR到环境配置到新建工程模板-以STM32为例 一、 简单介绍一下IAR软件1. IAR的安装(1) 下载IAR集成开发环境安装文件(2) 安装 2. 软件注册授权 二、IAR上手使用(基于STM32标准库新建工程)1、下载标准库文件2、在IAR新建工程&#x…...
FPGA优质开源项目 – PCIE通信
本文介绍一个FPGA开源项目:PCIE通信。该工程围绕Vivado软件中提供的PCIE通信IP核XDMA IP建立。Xilinx提供了XDMA的开源驱动程序,可在Windows系统或者Linux系统下使用,因此采用XDMA IP进行PCIE通信是比较简单直接的。 本文主要介绍一下XDMA I…...
NLP:长文本场景下段落分割(文本分割、Text segmentation)算法实践----一种结合自适应滑窗的文本分割序列模型
NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…...
商汤科技2021校招-开发大类B卷
笔试时间:2020.09.18,19:00——21:00 岗位:嵌入式软件工程师 题型:单选4道,不定项选择题2道,填空2道,编程2道。 1、单选 1、在一棵二叉树上第5层的结点数最多是:16 第1层1个 2^0 第2层2个 2^1 第3层4个 2^2 第n层 2^(n-1...
为Alchitry Au FPGA开发板外接JTAG接口的完整指南
1. 项目概述与核心价值如果你正在使用基于Xilinx Artix-7 FPGA的Alchitry Au或Au开发板,并且已经厌倦了每次调试或烧录都要依赖板载的USB-JTAG桥接芯片,或者你的项目已经将板载USB接口挪作他用,那么为你的开发板外接一个独立的JTAG调试器&…...
终极鼠标连点器使用指南:3分钟掌握高效自动化技巧
终极鼠标连点器使用指南:3分钟掌握高效自动化技巧 【免费下载链接】MouseClick 🖱️ MouseClick 🖱️ 是一款功能强大的鼠标连点器和管理工具,采用 QT Widget 开发 ,具备跨平台兼容性 。软件界面美观 ,操作…...
3分钟掌握HashCalculator:你的文件完整性守护专家
3分钟掌握HashCalculator:你的文件完整性守护专家 【免费下载链接】HashCalculator 哈希值计算工具,批量计算/批量校验/查找重复文件/改变哈希值等,支持集成到系统右键菜单 项目地址: https://gitcode.com/gh_mirrors/ha/HashCalculator …...
Owl-Alpha 新手快速上手指南
在处理大规模数据或构建高性能应用时,我们常常会遇到一个棘手的问题:如何在不阻塞主线程的情况下,高效地执行耗时任务?无论是处理图像、解析大型文件,还是进行复杂的数学运算,传统的单线程模式往往会让界面…...
MongoDB Limit 与 Skip 方法详解
MongoDB Limit 与 Skip 方法详解 引言 MongoDB 是一个高性能、可伸缩的文档存储系统,它提供了强大的数据存储和查询功能。在处理大量数据时,Limit 与 Skip 方法是 MongoDB 中常用的查询优化工具。本文将详细介绍 MongoDB 中的 Limit 与 Skip 方法,包括其基本用法、性能影响…...
defx.nvim 安装与配置完全教程:从零开始搭建高效文件管理系统 [特殊字符]
defx.nvim 安装与配置完全教程:从零开始搭建高效文件管理系统 🚀 【免费下载链接】defx.nvim :file_folder: The dark powered file explorer implementation for neovim/Vim8 项目地址: https://gitcode.com/gh_mirrors/de/defx.nvim defx.nvim …...
避坑指南:Unity中AABB碰撞检测失效的5种常见原因及解决方法
Unity中AABB碰撞检测失效的深度排查与解决方案在Unity开发中,AABB(轴对齐包围盒)碰撞检测是基础但容易出问题的环节。许多开发者都遇到过这样的情况:明明逻辑正确,测试时却出现物体穿透、碰撞时有时无等诡异现象。本文…...
基于CNN的食双星光变曲线自动化参数初估模型EBOP MAVEN
1. 项目概述与核心价值在恒星天体物理领域,食双星系统一直扮演着“宇宙实验室”的关键角色。通过分析两颗恒星相互绕转时周期性相互遮挡产生的光变曲线,我们可以像解谜一样,精确反演出恒星的质量、半径、轨道倾角等基本物理参数。这些参数是构…...
Godot 4.3随机地图性能优化:避开TileMap与RNG陷阱
1. 为什么刚写完第一版随机地图就崩溃?——从“能跑”到“能用”的真实断层你兴冲冲地照着教程敲完几十行GDScript,RandomNumberGenerator初始化了,for x in range(width)循环也套好了,甚至还在_draw()里用draw_rect()把每个格子都…...
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验
3大突破性功能:用HiveWE革新你的魔兽争霸III地图创作体验 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 还在为传统魔兽争霸III编辑器缓慢的加载速度和复杂的操作界面而烦恼吗?Hive…...
