java实现@Valid自定义注解

2023-11-16

@Valid注解是什么

用于验证被注解对象是否符合要求,当不符合要求时就会在方法中返回message的错误提示信息。

自定义注解

@Target({ElementType.FIELD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = XXXValidator.class)
@Repeatable(CheckXXX.List.class)
public @interface CheckXXX {

	String name() default "abc";

	int age() default 1;

	String message() default "111";

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

	Class<? extends Payload>[] payload() default {};
	@Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {
        CheckXXX[] value();
    }
}

@Target:值只能是枚举类ElementType,有以下一些值:

  • ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
  • ElementType.FIELD:允许作用在属性字段上
  • ElementType.METHOD:允许作用在方法上
  • ElementType.PARAMETER:允许作用在方法参数上
  • ElementType.CONSTRUCTOR:允许作用在构造器上
  • ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
  • ElementType.ANNOTATION_TYPE:允许作用在注解上
  • ElementType.PACKAGE:允许作用在包上

@Documented:只能用在注解上,如果一个注解@B,被@Documented标注,那么被@B修饰的类,生成文档时,会显示@B。如果@B没有被@Documented标注,最终生成的文档中就不会显示@B。这里的生成文档指的JavaDoc文档!

@Retention:定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中(生命周期长度 SOURCE < CLASS < RUNTIME ,前者能作用的地方后者一定也能作用。一般如果需要 在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要 在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用 CLASS注解;如果 只是做一些检查性的操作,比如@Override和@SuppressWarnings,则 可选用 SOURCE 注解):

  • source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略。
  • class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
  • runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。

@Constraint:限定自定义注解的方法。

@Repeatable:被元注解@Repeatable修饰的注解,可以在同一个地方使用多次。使用要点:

  • 在需要重复使用的注解上修饰 @Repeatable。
  • @Repeatable中的参数为被修饰注解的容器的类对象(class对象)。
  • 容器包含一个value方法,返回一个被修饰注解的数组。

校验器

public class XXXValidator implements ConstraintValidator<CheckXXX, Object> {

    private String name;

    private int age;

    @Override
    public void initialize(CheckTimeInterval constraintAnnotation) {
        this.name = constraintAnnotation.name();
        this.age = constraintAnnotation.age();
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(o);
        String name = (String)beanWrapper.getPropertyValue(name);
        int age = (Integer)beanWrapper.getPropertyValue(age);
        return age > 10 && name.equals("abc");
    }
}

ConstraintValidator<>:第二个参数表示注解修饰的对象类型。(类注解就是Object)
initialize():类初始化方法。
isValid():返回true表示校验通过,返回false表示校验失败,返回message的错误提示信息。

示例

使用一次的注解:

@Target({ ElementType.FIELD })
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = { VinValidator.class })
public @interface CheckVins {

    String message() default "格式错误,输入多行vin必须为17位!";

    int max();

    int itemLength();

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

    Class<? extends Payload>[] payload() default {};
}
public class VinValidator implements ConstraintValidator<CheckVins, String[]> {

    private int max;

    private int itemLength;

	@Override
    public void initialize(CheckVins constraintAnnotation) {
        max = constraintAnnotation.max();
        itemLength = constraintAnnotation.itemLength();
    }

    @Override
    public boolean isValid(String[] value, ConstraintValidatorContext context) {

        //没有该参数时不判断
        if(value == null){
            return true;
        }
        //最多输入200个vin
        else if (value.length > max) {
            return false;
        }
        //输入vin大于一个时,要求每个必须为17位
        if (value.length>1){
            for (String item : value) {
                if (item.length() != itemLength) {
                    return false;
                }
            }
        }
        return true;
    }
}
public class RequestDownloadRecord {
	...
	@CheckVins(max = 200, itemLength = 17)
	private String[] vin;
}

重复使用的注解:

@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE,
        ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = CheckTimeIntervalValidation.class)
@Documented
@Repeatable(CheckTimeInterval.List.class)
public @interface CheckTimeInterval {
    /**
     * 开始日期
     * @return field
     */
    String beginTime() default "startTime";

    /**
     * 查询参数时间类型
     * @return field
     */
    String timeType() default "LocalDateTime";

    /**
     * 结束日期
     * @return field
     */
    String endTime() default "endTime";

    /**
     * 日期间隔
     * @return field
     */
    int dayRange() default 30;

    String message() default "{org.hibernate.validator.referneceguide.chapter06.CheckCase.message}";

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

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

    @Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
            ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List {

        CheckTimeInterval[] value();
    }
}
public class CheckTimeIntervalValidation implements ConstraintValidator<CheckTimeInterval, Object> {

    private String beginTime;

    private String endTime;

    private int dayRange;

    private String timeType;

    @Override
    public void initialize(CheckTimeInterval constraintAnnotation) {
        this.beginTime = constraintAnnotation.beginTime();
        this.endTime = constraintAnnotation.endTime();
        this.dayRange = constraintAnnotation.dayRange();
        this.timeType=constraintAnnotation.timeType();
    }

    @Override
    public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
        BeanWrapper beanWrapper = new BeanWrapperImpl(o);
        long result=0;
        if ("LocalDateTime".equals(timeType)){
            LocalDateTime begin = (LocalDateTime) (beanWrapper.getPropertyValue(beginTime));
            LocalDateTime end = (LocalDateTime) (beanWrapper.getPropertyValue(endTime));
            if (null == begin || null == end) {
                return false;
            }
            // result = end.compareTo(begin);
            result=begin.until(end, ChronoUnit.DAYS);
        }else if ("LocalDate".equals(timeType)){
            LocalDate begin = (LocalDate) (beanWrapper.getPropertyValue(beginTime));
            LocalDate end = (LocalDate) (beanWrapper.getPropertyValue(endTime));
            if (null == begin || null == end) {
                return false;
            }
            result=begin.until(end, ChronoUnit.DAYS);
        }

        return result>=0&&result <= dayRange;
    }
}
@CheckTimeInterval(beginTime = "start",endTime = "end",timeType="LocalDateTime",dayRange = 14,message = "开始时间必须小于结束时间,只能查询14天的日期范围数据")
@CheckTimeInterval(beginTime = "start",endTime = "end",timeType="LocalDateTime",dayRange = 28,message = "开始时间必须小于结束时间,只能查询28天的日期范围数据")
public class RunningRecordQuery {
	...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java实现@Valid自定义注解 的相关文章

  • Amazon Elasticache Redis 集群 - 无法获取端点

    我需要获取 Amazon Elasticache 中 Redis 集群的终端节点 以下代码适用于 Memcached 集群 但不适用于 Redis import com amazonaws auth AWSCredentials impor
  • 探索java图像处理的好资源[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是图像处理领域的新手 请推荐一些好的资源 书籍和网络链接 来学习 Java 中的图像处理 最适合隐写术分析 适合初学者和高级水平 我看过
  • 如果主引用指向 null,WeakReference 或 SoftReference 有何不同

    我正在读关于WeakReference https docs oracle com javase 10 docs api java lang ref WeakReference html and SoftReference https do
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • 如何添加 Java 正则表达式实现中缺少的功能?

    我是 Java 新手 作为一名 Net 开发人员 我非常习惯Regex Net 中的类 Java 实现Regex 正则表达式 还不错 但它缺少一些关键功能 我想为 Java 创建自己的帮助器类 但我想也许已经有一个可用的了 那么 是否有任何
  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • 使用 Hibernate Criteria 过滤 Map 中的键和值

    我有以下持久类 public class Code ElementCollection targetClass CodeValue class MapKeyClass CodeProperty class JoinTable name co
  • 生产者程序中的 kafka 网络处理器错误(ArrayIndexOutOfBoundsException:18)

    我有下面的 kafka Producer Api 程序 我对 kafka 本身是新手 下面的代码从 API 之一获取数据并将消息发送到 kafka 主题 package kafka Demo import java util Propert
  • java数学中的组合“N选择R”?

    java库中是否有内置方法可以为任何N R计算 N选择R 公式 实际上很容易计算N choose K甚至不需要计算阶乘 我们知道 公式为 N choose K is N N K K 因此 公式为 N choose K 1 is N N N
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • Java:java.util.Preferences 失败

    我的程序将加密的产品密钥数据保存到计算机上java util Preferences类 系统首选项 而不是用户 问题是 在 Windows 和 Linux 上 尚未在 OSX 上测试过 但可能是相同的 如果我不运行该程序sudo或者具有管理
  • 如何加载图像文件到ImageView?

    我试图在从文件选择器中选择图像文件后立即显示该图像文件 文件选择器仅限于 png 和 jpg 文件 所选文件存储在文件类型的变量中 为此 我设置了一个 ImageView 我希望用这个新文件设置图像 唯一的问题是它的类型是文件而不是图像 如
  • 如何在启用嵌入时间戳和 LTV 的情况下签署 PDF?

    我正在尝试签署启用了时间戳和 LTV 的 pdf 以便它在 Adob e Reader 中显示如下 在英语中 这意味着 签名包含嵌入的时间戳 和 签名启用了 LTV 这是我正在使用的代码 PrivateKey pk get pk from
  • 应用程序中空指针异常[重复]

    这个问题在这里已经有答案了 我正在尝试在我的应用程序中实施应用程序内计费 我写了这段代码 public class Settings extends PreferenceFragment ServiceConnection mService
  • 将 PropertyPlaceholderConfigurer 中的所有属性注入到 bean 中

    我有一个PropertyPlaceholderConfigurer加载多个属性文件 我想通过配置 XML 将合并的属性映射注入到 Spring Bean 中 我可以这样做以及如何做 您只需创建一个属性 bean 并将其用于您的Propert
  • 线程上下文类加载器和普通类加载器的区别

    线程的上下文类加载器和普通类加载器有什么区别 也就是说 如果Thread currentThread getContextClassLoader and getClass getClassLoader 返回不同的类加载器对象 将使用哪一个
  • 测量 tomcat 的排队请求数

    因此 使用tomcat 您可以设置acceptCount值 默认为100 这意味着当所有工作线程都忙时 新连接被放置在队列中 直到队列满 之后它们被拒绝 我想要的是监视此队列中项目的大小 但无法确定是否有办法通过 JMX 获取此值 即不是队
  • 在java中创建一个XML树并将其转换为json对象

    我尝试创建也能够转换为 json 的树 但对于只有一个xpath 当我尝试实现多个 xpath 时 我无法获得所需的输出 这里我分享一下我的实现 private static Document addElemtbypath List
  • AES 密钥是随机的吗?

    AES 密钥可以通过此代码生成 KeyGenerator kgen KeyGenerator getInstance AES kgen init 128 but 如果我有一个 非常可靠 的生成随机数的方法 我可以这样使用它吗 SecureR
  • 检查 Java 字符串实例是否可能包含垃圾邮件数据的最简单方法

    我有一个迭代 String 实例的过程 每次迭代对 String 实例执行很少的操作 最后 String 实例被持久化 现在 我想为每次迭代添加一个检查 String 实例是否可能是垃圾邮件的检查 我只需验证 String 实例不是 成人材

随机推荐

  • Python-集合

    探索Python集合的奇妙世界 在Python编程中 集合 Set 是一种强大且有用的数据结构 它用于存储多个不重复的元素 集合的独特之处在于它的元素是无序的 并且每个元素都是唯一的 这使得集合在处理去重和进行快速成员检查时非常有效 创建集
  • 手把手带你打造自己的UI样式库(第五章)之常用页面切图的设计与开发

    常用页面切图的设计与开发 在一些大的前端团队中 前端工程师这个职位会出现一个分支 叫做重构工程师 重构工程师主要负责 HTML 和 CSS 的制作 也就是把设计稿转换成 HTML 和 CSS 代码 重构工作完成以后 把制作好的 HTML 和
  • 【第十四届蓝桥杯单片机组底层驱动测试】

    第十四届蓝桥杯单片机组底层驱动测试 下面分享的是第十四届蓝桥杯单片机组底层驱动代码的测试和相关说明 今年官方提供的资料包中底层驱动代码和以往有了变化 主要代码还是提供给了我们 只是此次没有了相关头文件iic h ds1302 onewire
  • win10剪贴板快捷键win+v

    win v可以出现最近10多次粘贴的数据
  • Ioc容器refresh总结(3)--- Spring源码从入门到精通(三十三)

    上篇文章介绍了 调用bean工厂的后置处理器 主要分为两步 他是在beanFactory预准备标准初始化之后执行invokBeanFactoryPostProcessor 先调用beanDefinitionRegistryPostProce
  • [paper] MTCNN

    MTCNN 论文全称 Joint Face Detection and Alignment using Multi task Cascaded Convolutional Networks 论文下载链接 https arxiv org ab
  • vue.js基础学习(模板语法)

    基础入门 vue js模板语法 1 模板语法 methods 给vue定义方法 this 指向当前vue实例 v html 让内容以HTML形式编译 v bind 绑定动态数据 v noce 当数据发生改变时 插值处内容不发生改变 动态属性
  • maven相关

    1 webxml attribute is required or pre existing WEB INF web xml if executing in update 原因 web项目下缺少 WEB INF web xml 在servl
  • 【AWS】API Gateway创建Rest API--从S3下载文件

    一 背景 在不给AK SK的前提下 用户查看s3上文件 从s3下载文件 二 创建API 1 打开API Gateway 点击创建API 选择REST API REST API和HTTP API区别 来自AWS官网 REST API 和 HT
  • 算法——查找

    文章目录 一 基本概念和评价 1 相关概念 2 查找表 2 1 常见操作 2 2 分类 3 查找算法的评价指标 二 线性结构查找 1 顺序查找算法 1 1 定义 1 2 算法思想 1 3 特点 1 4 分类 1 无哨兵的无序线性表的顺序查找
  • Unity 安卓报错 failed to extract resources needed by IL2cpp

    Unity打出来的包在自己的PC放置好文件后 运行能够正常运行 但是git提交之后 别的机器拉代码下来报错 failed to extract resources needed by IL2cpp 这里推测原因是 安卓包打出来的Asset
  • TikTok逆向,全球的小姐姐们,我来啦!

    作者 AYJk 链接 https juejin im post 5c19a38ae51d453e0a209256 开源地址 首先抛出GitHub地址吧 多多支持指点 谢谢 AYTikTokPod https github com AYJk
  • 知识索引目录

    author skate time 2012 11 22 存储 io系统的压力测试工具 fio http blog csdn net wyzxg article details 7454072 iozone使用 http blog csdn
  • 从零开发一套完整的react项目开发环境

    不管是工作需要还是面试加分 除了Vue相关技术以外 React技术栈也已经成为了前端开发工程师必备的技术点 接下来 我将从零开发一套完整的React全家桶项目开发环境 提供给需要的同行小伙伴观看也方便自己以后复习 篇幅很长 请需要的小伙伴耐
  • ZLMediaKit+wvp-GB28181-pro 安装文档

    文章目录 前言 1 安装zlm 1 1 镜像说明 1 2 docker安装 1 2 1 docker安装命令 1 2 2 docker compose安装 1 3 zlm配置和日志重点说明 2 安装wvp 2 1 目录结构说明 2 1 1
  • 汇编宏伪指令介绍

    1 汇编宏伪指令介绍 macro macname macargs endm 1 macro 和 endm 表示宏定义的开始和结束 2 macro 后面接着宏定义的名字 然后是参数 参数后面的宏定义的实现 3 在宏定义中使用参数 需要添加前缀
  • Eclipse中Web项目开发与Tomcat发布的的路径问题详解

    本人以前对Web项目的开发路径和发布路径等一直都很懵逼 今天找到了一片文章 里面写得很详细 在这里转载分享给大家 https www cnblogs com teach p 5669873 html
  • STM32F407输入捕获应用--PWM 输入模式测量脉冲频率与宽度

    STM32F407输入捕获应用 PWM 输入模式测量脉冲频率与宽度 一 测量脉宽或者频率 二 PWM 输入模式 三 软件实现 3 1 硬件准备 3 2代码 3 4 验证 输入捕获一般应用在两个方面 一个方面是脉冲跳变沿时间测量 另一方面 是
  • PyTorch-06 过拟合&欠拟合、Train-Val-Test划分、Regularization减轻防止overfitting、动量与学习率衰减、其他技巧Early Stop,Dropout

    PyTorch 06 过拟合 欠拟合 Train Val Test划分 Regularization减轻防止overfitting 动量与学习率衰减 其他技巧Tricks Early Stop Dropout 一 过拟合 欠拟合 讨论过拟合
  • java实现@Valid自定义注解

    Valid注解是什么 用于验证被注解对象是否符合要求 当不符合要求时就会在方法中返回message的错误提示信息 自定义注解 Target ElementType FIELD Documented Retention RetentionPo