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

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 前端传递参数,需要进行唯一性校验的字段

![在这里插入图片描述](https://img-blog.csdnimg.cn/e613f37d22554914940b3a162ed0916c.png

3.6.2 message提示

在这里插入图片描述

相关文章:

Java自定义校验注解实现List、set集合字段唯一性校验

文章目录 一&#xff1a; 使用场景二&#xff1a; 定义FieldUniqueValid注解2.1 FieldUniqueValid2.2 注解说明2.3 Constraint 注解介绍2.4 FieldUniqueValid注解使用 三&#xff1a;自定义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】本地电脑搭建个人博客网站&#xff08;并发布公网访问 &#xff09;和web服务器 文章目录 【无公网IP】本地电脑搭建个人博客网站&#xff08;并发布公网访问 &#xff09;和web服务器前言1. 安装套件软件2. 创建网页运行环境 指定网页输出的端口号3. 让WordPress在…...

SpringCloud(29):Nacos简介

1 什么是配置中心 1.1 什么是配置 应用程序在启动和运行的时候往往需要读取一些配置信息&#xff0c;配置基本上伴随着应用程序的整个生命周期&#xff0c;比如&#xff1a;数据库连接参数、启动参数等。 配置主要有以下几个特点&#xff1a; 配置是独立于程序的只读变量 …...

freeBSD - 笔记

1 介绍 FreeBSD&#xff1a; FreeBSD是由FreeBSD项目团队开发的&#xff0c;最早可以追溯到1993年。它专注于性能、稳定性和可靠性&#xff0c;并在服务器和高性能计算环境中广泛使用。FreeBSD有着强大的网络性能和高度优化的TCP/IP协议栈&#xff0c;因此在网络服务器领域表…...

【Linux】网络基础——宏观认识计算机网络

1 计算机网络背景 网络发展 独立模式: 计算机之间相互独立; 一开始&#xff0c;计算机发明出来之后&#xff0c;一台计算机处理完的数据&#xff0c;数据会保存在软盘&#xff08;物理&#xff09;&#xff0c;通过人之间的相互通信&#xff0c;把计算机A处理完的数据存储到软…...

数字人现身大运会,怎么以动作捕捉技术助推运动与文博相结合

中国移动动感地带数字人橙络络&#xff0c;作为数智体验官以元宇宙的视角&#xff0c;带领观众沉浸式体验大运会&#xff0c;以极具科技和未来的数字人&#xff0c;对外传递大运青春风采&#xff0c;并且数字人橙络络还对大运会的赛事、活动进行了科普、讲解以及表演当地特色才…...

WSL安装

WSL安装 1.Microsoft store 安装 1.1 启动WSL功能 在【程序和功能 -> 启用或关闭 Windows 功能】中勾选【适用于 Linux 的 Windows 子系统】 1.2 Store中下载安装 在 Microsoft Store 中下载并安装需要的 Linux 发行版 2.不使用Store安装WSL 注&#xff1a;1.1也要…...

MongoDB 入门

1.1 数据库管理系统 在了解MongoDB之前需要先了解先数据库管理系统 1.1.1 什么是数据&#xff1f; 数据&#xff08;英语&#xff1a;data&#xff09;&#xff0c;是指未经过处理的原始记录。 一般而言&#xff0c;数据缺乏组织及分类&#xff0c;无法明确的表达事物代表的意…...

使用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全局敏感性分析模型运用&#xff08;含无目标函数&#xff0c;考虑代理模型&#xff09; 版本更新&#xff1a; 2023/8/5&#xff1a; 1.因BP作为代理模型不稳定&#xff0c;经过测试&#xff0c;libsvm比rf /bp 效果稳定且精…...

Python web实战之Django用户认证详解

关键词&#xff1a; Python Web 开发、Django、用户认证、实战案例 概要 今天来探讨一下 Django 的用户认证吧&#xff01;在这篇文章中&#xff0c;我将为大家带来一些有关 Django 用户认证的最佳实践。 1. Django 用户认证 在开发 Web 应用程序时&#xff0c;用户认证是一个…...

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…...

生信学院|08月18日《基于Flow Simulation的冷链运输产品案例》

课程主题&#xff1a;基于Flow Simulation的冷链运输产品案例 课程时间&#xff1a;2023年08月18日 14:00-14:30 主讲人&#xff1a;江流洋 生信科技 CAE专家 1、达索仿真方案介绍 2、项目介绍 3、案例分析 请安装腾讯会议客户端或APP&#xff0c;微信扫描海报中的二维码…...

不可错过的家装服务预约小程序商城开发指南

在当今社会&#xff0c;家装行业发展迅速&#xff0c;越来越多的人开始寻求专业的家装预约和咨询服务。对于不懂技术的新手来说&#xff0c;创建一个自己的家装预约咨询平台可能听起来很困难&#xff0c;但实际上通过一些第三方制作平台和工具&#xff0c;这个过程可以变得简单…...

任务 13、MidJourney种子激发极致创作,绘制震撼连贯画作

13.1 任务概述 通过本次实验任务&#xff0c;学员将深入了解Midjourney种子的概念和重要性&#xff0c;以及种子对生成图像的影响。他们将学会在Midjourney平台中设置种子值并调整其参数&#xff0c;以达到所需的效果。此外&#xff0c;任务还详细介绍了Midjourney V4.0版本中…...

IAR开发环境的安装、配置和新建STM32工程模板

IAR到环境配置到新建工程模板-以STM32为例 一、 简单介绍一下IAR软件1. IAR的安装&#xff08;1&#xff09; 下载IAR集成开发环境安装文件&#xff08;2&#xff09; 安装 2. 软件注册授权 二、IAR上手使用(基于STM32标准库新建工程)1、下载标准库文件2、在IAR新建工程&#x…...

FPGA优质开源项目 – PCIE通信

本文介绍一个FPGA开源项目&#xff1a;PCIE通信。该工程围绕Vivado软件中提供的PCIE通信IP核XDMA IP建立。Xilinx提供了XDMA的开源驱动程序&#xff0c;可在Windows系统或者Linux系统下使用&#xff0c;因此采用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...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...