用自定义类级注解校验两字段不能同时为空

news2024/9/23 11:16:17

背景:

有下面这么一个类,要校验两字段query、image不能同时为空,应该怎么实现?已知的@NotBlank等标签都只能检验单个字段。

import jakarta.validation.constraints.NotBlank;
import lombok.Data;
import org.springframework.http.codec.multipart.FilePart;

@Data
public class MultiModalQARequest {
。。。。

    /**
     * 用户提问
     */
    @NotBlank(message = "query不能为空")
    private String query;

    private FilePart image;

}


解决:

参考https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=8.0#section-class-level-constraints中的在这里插入图片描述
我有以下实现:

import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = {NotBothBlankValidator.class})
@Documented
public @interface NotBothBlank {

    String message() default "两个字段不能同时为空";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String firstFieldName();

    String secondFieldName();
}

import com.zju.design.aiplatformdemo2.utils.StringUtil;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.function.BiFunction;

@Slf4j
public class NotBothBlankValidator
        implements ConstraintValidator<NotBothBlank, Object> {

    private NotBothBlank constraintAnnotation;

    @Override
    public void initialize(NotBothBlank constraintAnnotation) {
        this.constraintAnnotation = constraintAnnotation;
    }

    private static BiFunction<Object, Field, Boolean> isBlank = (object, field) ->
    {
        log.info("NotBothBlankValidator field type {}", field.getType());
        try {
            field.setAccessible(true);
            return (String.class.isAssignableFrom(field.getType()) ? StringUtil.isBlank((String) field.get(object)) : field.get(object) == null);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    };

    @Override
    public boolean isValid(Object validatedObject, ConstraintValidatorContext context) {
        if (validatedObject == null) {
            return true;
        }
        //通过反射拿到validatedObject对象的firstFieldName和secondFieldName字段的值,判断它们不能同时为空:
        try {
            Field firstField = validatedObject.getClass().getDeclaredField(constraintAnnotation.firstFieldName());
            Field secondField = validatedObject.getClass().getDeclaredField(constraintAnnotation.secondFieldName());
            return !(isBlank.apply(validatedObject, firstField) && isBlank.apply(validatedObject, secondField));
        } catch (Exception e) {
            log.error("NotBothBlankValidator error", e);
            throw new RuntimeException(e);
        }
    }
}

业务代码的变更:
在这里插入图片描述

测试可用。

其它相关文档:

https://stackoverflow.com/questions/54638255/spring-boot-validation-one-from-two-not-null

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101327.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

无人机之载重篇

无人机的载重能力是一个复杂且多样化的参数&#xff0c;它受到多种因素的影响&#xff0c;包括无人机的类型、设计、技术规格以及用途等。以下是对无人机载重能力的详细解析&#xff1a; 一、无人机载重能力的差异 无人机的载重能力差异很大&#xff0c;从几百克到几十千克不等…

全网都在学,2024最新大模型畅销的三本书!千言万语,尽在书中

哈咯各位&#xff0c;我们都知道2024年最火爆的技术非大模型莫属&#xff0c;而今天就给大家分享几本大模型方向2024年新出的书籍&#xff0c;主要分享这三本非常畅销的书----《Transformer自然语言处理实战》&#xff0c;《实战AI大模型》&#xff0c; 《精通Transformer&…

草原灭火车的功能与性能_鼎跃安全

在内蒙古的草原火灾中&#xff0c;水陆两栖全地形草原灭火车曾多次用于紧急救援。其强大的越野能力和高速反应&#xff0c;使其在广袤的草原上能够迅速到达火场&#xff0c;并使用集成的多功能灭火设备进行灭火作业&#xff0c;有效防止了火灾的进一步蔓延。 水陆两栖全地形草原…

SpringDataJPA系列(4)Repository 中的方法返回值使用

SpringDataJPA系列(4)Repository 中的方法返回值使用 Repository 返回结构有哪些&#xff1f; 打开 SimpleJpaRepository 直接看它的 Structure 就可以知道&#xff0c;它实现的方法&#xff0c;以及父类接口的方法和返回类型包括&#xff1a;Optional、Iterable、List、Page…

S-MLAG-简单跨设备链路聚合

资料&#xff1a; https://www.h3c.com/cn/Service/Document_Software/Document_Center/Home/Switches/00-Public/Configure/Practice/H3C_S_MLAG-BP_Long/#_Toc115363852https://www.h3c.com/cn/d_202010/1348323_30005_0.htm#_Toc53156759 S-MLAG概述 S-MLAG简介 通过S-M…

CSS 高级区块效果——WEB开发系列25

CSS提供了多种工具和属性&#xff0c;使我们能够创建视觉上引人注目的效果。今天我们继续将深入了解几种高级CSS效果&#xff1a;盒子阴影、滤镜、混合模式和文本背景裁剪&#xff0c;提升网页设计的质感和深度。 一、盒子阴影&#xff08;Box Shadow&#xff09; 对于盒子元素…

申请联通卡时,为什么需要上传身份证呢?

我们在后台收到了很多朋友的私信&#xff0c;除了咨询流量卡套餐方面的问题之外&#xff0c;也有不少朋友是咨询流量卡申请方面的问题&#xff0c;今天&#xff0c;小编就回答一个很有代表性的问题&#xff0c;为什么申请联通卡时要上传身份证信息&#xff0c;而其他的运营商就…

局域网IP地址老是冲突/环路?这个关键点绝对被你忽略了

号主&#xff1a;老杨丨11年资深网络工程师&#xff0c;更多网工提升干货&#xff0c;请关注公众号&#xff1a;网络工程师俱乐部 下午好&#xff0c;我的网工朋友。 在现代企业环境中&#xff0c;局域网(LAN)是支撑日常业务运营的关键基础设施之一。 但随着网络规模的不断扩…

12、Django Admin在列表视图页面上显示计算字段

两种方法&#xff1a; 注册模型有两种方式&#xff0c;需要首先添加或者修改admin中的注册模型如下方式 admin.register(Origin) class OriginAdmin(admin.ModelAdmin):list_display ("name",) 1、在models的模型类中添加函数 def hero_count(self,):return sel…

大学生就业必备的2款软件!助你轻松化身Offer收割机!

金秋九月&#xff0c;又是一年开学季&#xff0c;随之而来也有许多大学生要开始找工作&#xff0c;但现在的情况是&#xff0c;大部分岗位有很多人同时申请&#xff0c;要想从激烈的竞争中脱颖而出&#xff0c;少不了在求职的每一个环节上下功夫。 最受求职的企业注意的&#…

ubuntu linux搭建lvgl

记录一下ubuntu linux搭建 lvgl的过程 本地环境:ubuntu 16.04 ubuntu lvgl sdl2 1 获取源码 git clone https://github.com/lvgl/lv_port_linux.git cd lv_port_linux/ git submodule update --init --recursive查看分支: git branch -a 我选择的是9.2(master分支一直在变动…

DeepWalk【图神经网络论文精读】笔记

链接: DeepWalk【图神经网络论文精读】_哔哩哔哩_bilibili [内容总结::] - deep walk 解决图嵌入问题&#xff1a;将结点压缩成低维向量随机游走&#xff08;类似NLP生成句子&#xff09; 优点与缺点: 相关学习资料 - word2vec 开山必读论文 - DeepWalk 论文阅读 - 代…

erlang学习:用OTP构建系统4,监控树学习

监控树学习 之前写的server程序&#xff0c;如果产生了错误&#xff0c;server会立刻停止。本次学习使用了监控树&#xff0c;能够让server崩溃时打印错误信息并重启服务器&#xff0c;能够使服务器正常使用 -module(sellaprime_supervisor). -behaviour(supervisor). -expor…

iPhone升级iOS 18后遭遇“白苹果”?别怕,这几招教你轻松应对!

在这个科技日新月异的时代&#xff0c;苹果iOS系统的每一次更新都牵动着亿万果粉的心。iOS 18作为苹果最新的操作系统&#xff0c;不仅带来了全新的功能体验&#xff0c;也难免会遇到一些用户反馈的“小插曲”&#xff0c;比如升级后出现的“白苹果”现象。面对这一状况&#x…

系统编程-UDP

UDP 目录 UDP 引入 使用 UDP 的注意事项 一、单播的流程 -- 一对一 如何实现端口和地址重复绑定 二、广播的流程 -- 一对多 三、组播的流程 -- 多对多 加入组播&#xff0c;需要使用 setsockopt 函数 主要代码 -- 主要是发送方 引入 -- UDP协议的特点 无连接性&…

24:【stm32】DMA数据搬运

DMA数据搬运 1、DMA的简介2、STM32中的DMA结构3、案列3.1、将数组DataA中的数据搬运到DataB中3.2、ADC扫描模式DMA 1、DMA的简介 DMA是直接存储器存取&#xff0c;它可以提供外设寄存器和存储器&#xff0c;存储器与存储器之间的高速数据的传输&#xff0c;无需CPU的干预&…

通配符证书的申请及配置教程

在当今高度互联的世界里&#xff0c;网站和应用程序需要确保其数据传输的安全性&#xff0c;以保护用户的隐私和敏感信息不被窃取。为此&#xff0c;HTTPS协议成为了标准配置&#xff0c;而SSL/TLS证书则是实现这一安全协议的重要组成部分。特别地&#xff0c;对于那些运营着多…

asp.net core web api项目添加自定义中间件

前言 在asp.net core web api项目中&#xff0c;默认提供了很多的中间件&#xff0c;比如访问静态文件中间件UseStaticFiles&#xff0c;跨域配置中间件UseCors&#xff0c;路由中间件UseRouting,身份验证中间件UseAuthentication。 那么如何添加一些自定义的中间件呢。 需求…

【数据结构】单链表功能的实现

目录 1.链表的概念及结构 2.单链表功能的实现 2.1打印单链表 2.2创建节点 2.3单链表尾插 2.3单链表头插 2.5单链表尾删 2.6单链表头删 2.7单链表的查找 2.8在指定位置之前插入数据 2.9在指定位置之后插入数据 2.10删除pos节点 2.11删除pos之后的节点 2.12销毁链表…

快专利与慢专利:速度与质量的天平

在当今快速发展的科技时代&#xff0c;专利成为了创新成果的重要保护手段。然而&#xff0c;不同的创新有着不同的节奏&#xff0c;由此也产生了“快专利”与“慢专利”之分。快专利以其迅速的申请和应用&#xff0c;为创新者抢占市场先机&#xff1b;慢专利则凭借深度的研发和…