项目开发中会经常使用到各种枚举值,枚举值一般都是固定的,不会随意改变其中的值。

比如性别分为男女,确定之后一般都不会轻易改变,这时候使用枚举值就非常地方便。很多

时候,在页面中传入的参数就是枚举值中的一个,比如性别,或者是星期,月份,以及自定义

的各种类型等等。如果是手动校验就非常麻烦,假如有50个枚举值,不可能每一个枚举值都

进行手动校验,那这时候如何更好的校验呢?答案很简单,使用自定义的校验注解即可。

先上代码,然后在慢慢地讲解。自定义的校验注解如下:

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Constraint(validatedBy = {EnumValidateValidator.class})

public @interface EnumValidate {

Class<? extends Enum<?>> enumClass();

String enumMethod() default "isValid";

String message() default "必须传入枚举类型的class";

boolean nullAble() default false;

//分组

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

// 负载

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

// 指定多个时使用

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@interface List {

EnumValidate [] value();

}

}

自定义校验注解验证器如下:

public class EnumValidateValidator implements ConstraintValidator<EnumValidate, Object> {

private Class<? extends Enum<?>> enumClass;

private String enumMethod;

private boolean nullAble;

@Override

public void initialize(EnumValidate constraintAnnotation) {

enumClass = constraintAnnotation.enumClass();

enumMethod = constraintAnnotation.enumMethod();

nullAble = constraintAnnotation.nullAble();

}

@Override

public boolean isValid(Object value, ConstraintValidatorContext context) {

if (value == null) {

return nullAble;

}

try {

Object[] enumConstants = enumClass.getEnumConstants();

Method method = enumClass.getMethod(enumMethod, value.getClass());

Object result = method.invoke(enumConstants[0], value);

System.out.println("invoke--->" + result);

return (Boolean)result;

} catch (Exception ex) {

ex.printStackTrace();

throw new RuntimeException("枚举类型验证错误");

}

}

}

自定义的测试枚举如下:

public enum  TestEnum {

TYPE_ONE("ONE", "成功"),

TYPE_TWO("TYPE_TWO", "失败"),

;

/*

* 编码

*/

private String code;

/*

* 信息

*/

private String msg;

public String getCode() {

return code;

}

TestEnum(String code, String msg) {

this.code = code;

this.msg = msg;

}

/* @Description: 枚举里面的自定义校验方法

* @author: yilang

* @date: 2022/12/6 20:53

* @param: value

* @return: boolean

*/

public boolean isValid(String value) {

for(TestEnum testEnum : TestEnum.values()) {

if (testEnum.getCode().equals(value)) {

return true;

}

}

return false;

}

}

测试入参如下:

@Data

public class ParamTest {

/*

* 名称

*/

@NotNull(message = "名称不能为null")

private String name;

/*

* 简介

*/

@Length(max = 10, message = "简介长度最大为10")

private String abs;

@EnumValidate(enumClass = TestEnum.class, nullAble = false, message = "传入的枚举类型参数错误")

private String enumTest;

}

Controller中的测试方法如下:

@Slf4j

@RestController

@RequestMapping("/happy/yilang")

public class TestControlelr {

@PostMapping("/enum")

public String enumTest(@Valid @RequestBody ParamTest paramTest){

return "枚举类型统计";

}

}

自定义注解中主要有几个自定参数,

// 限定传入的class为枚举类型

Class<? extends Enum<?>> enumClass();

// 指定传入的需要调用的枚举类的检验方法

String enumMethod() default "isValid";

// 错误提示信息

String message() default "必须传入枚举类型的class";

// 待校验的参数是否允许为null

boolean nullAble() default false;

//分组-自定义注解最好加上

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

// 负载-自定义注解必加参数,否则报错

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

自定义注解校验器EnumValidateValidator 需要实现接口ConstraintValidator,然后重写里面的校验方法。

// 返回枚举类的元素 enumClass是通过注解拿到的,然后初始化的时候赋值给成员变量

Object[] enumConstants = enumClass.getEnumConstants();

// 获取需要执行的方法 enumMethod是通过注解拿到的,然后初始化的时候赋值给成员变量

//  value.getClass() 可以获取到原始传入数据的类型

Method method = enumClass.getMethod(enumMethod, value.getClass());

// 使用反射的方式执行方法,传入枚举变量和参数 程序底层会调用注解中获取到的需要执行的校验方法,默认为isValid,可以任意修改

Object result = method.invoke(enumConstants[0],  value);

// 自定义枚举类中isValid 方法返回的值是一个Object类型,可以转换为布尔类型

return (Boolean)result;

自定义枚举类中, isValid是自定义方法,名称可以随便取。 TestEnum.values()是每一个枚举类中都自带的方法,可以获取当前枚举的所有值。

public boolean isValid(String value) {

for(TestEnum testEnum : TestEnum.values()) {

if (testEnum.getCode().equals(value)) {

return true;

}

}

return false;

}

Controller中的方法和参数中使用注解的方式都很常规,不在赘述。

测试结果如下,通过校验的测试

未通过校验的测试

参考文章:

https://blog.csdn.net/h2604396739/article/details/83825148

Java自定义注解校验枚举值类型参数的更多相关文章

  1. Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)

    Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性) 前言:由于前段时间忙于写接口,在接口中需要做很多的参数校验,本着简洁.高效的原则,便写了这个小工具供自己使用(内容 ...

  2. Java 自定义注解 校验指定字段对应数据库内容重复

    一.前言 在项目中,某些情景下我们需要验证编码是否重复,账号是否重复,身份证号是否重复等... 而像验证这类代码如下: 那么有没有办法可以解决这类似的重复代码量呢? 我们可以通过自定义注解校验的方式去 ...

  3. java自定义注解实现前后台参数校验

    2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...

  4. java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题

    一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...

  5. Java自定义注解和运行时靠反射获取注解

    转载:http://blog.csdn.net/bao19901210/article/details/17201173/ java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编 ...

  6. java自定义注解类

    一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...

  7. java自定义注解注解方法、类、属性等等【转】

    http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...

  8. JAVA自定义注解 ------ Annotation

    日常开发工作中,合理的使用注解,可以简化代码编写以及使代码结构更加简单,下面记录下,JAVA自定义注解的开发过程. 定义注解声明类. 编写注解处理器(主要起作用部分). 使用注解. 相关知识点介绍, ...

  9. Java自定义注解的实现

    Java自定义注解的实现,总共三步(eg.@RandomlyThrowsException): 1.首先编写一个自定义注解@RandomlyThrowsException package com.gi ...

  10. java 自定义注解以及获得注解的值

    1.自定义注解 import java.lang.annotation.*; @Documented @Target(ElementType.FIELD) @Inherited @Retention( ...

随机推荐

  1. 小白学k8s(1)二进制部署k8s

    二进制部署k8s 前言 准备工作 关闭防火墙 关闭 swap 分区 关闭 SELinux 更新系统时间 秘钥免密码 设置主机名称 服务器角色 安装etcd 创建证书 生成证书 部署Etcd 在Node ...

  2. TPopupMenu 替换 自身自动的 热键

    有时候自动生成的热键 并不是 很理想 这个时候 需要 用自己认为好的 方法如下图,加个(&热键)

  3. CentOS7.5上卸载Oracle19c

    最近遇到一个麻烦的事情,由于公司开发的数据库备份容灾系统,对于备份容灾的数据库必须使用LVM(pv.vg.lv),所以之前安装的Oracle19C 必须卸载掉,然后使用空白磁盘通过parted.fdi ...

  4. [Spring]Junit单元测试时取不到本地文件问题

    Junit单元测试时取不到本地文件问题 问题 当使用Junit进行单元测试时,遇到了以下问题: 2022-10-24 16:13:19.902 [main] ERROR zonetop.gisboot ...

  5. UVA12024 Hats 题解

    题目传送门 前置知识 错位排列 题意 有 \(t\) 组询问,每次询问给定一个 \(n\),表示有 \(n\) 个人,每人各有一个属于自己的帽子,求所有人都带错帽子的概率(不要求约分至最简形式). 解 ...

  6. 华为云GaussDB支撑农行超级网银业务,性能和稳定性备受认可

    数据库作为数据驱动业务创新和智慧银行建设的关键基础设施,在银行数字化变革中具有举足轻重的作用. 在金融科技发展和国家政策引领下,银行纷纷加快推进数字化转型时代,正在经历一场以科技引领.数据赋能.数字经 ...

  7. JS Leetcode 264. 丑数 II 题解分析,当暴力无法暴力,让我们弃武从文了解三指针

    壹 ❀ 引 我在JS Leetcode 263. 丑数 题解分析,来认识有趣的丑数吧一文中记录了简单难度的丑数题,那么这篇题解是它的升级版,题目来自LeetCode264. 丑数 II,题目描述如下: ...

  8. ckeditor实战总结

    介绍 使用范围较广的富文本编辑器.官方文档 config.js的常用配置 参考:https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_conf ...

  9. 【CVE-2024-21626】容器逃逸漏洞修复

    哈喽大家好,我是咸鱼. 好久不见,最近有一个很火的 CVE--runc 容器逃逸漏洞.年前的时候我们已经在测试环境进行了相关操作打算年后线上进行修复. 因为今天咸鱼才开工,所以文章也就拖到了现在 漏洞 ...

  10. [BUUCTF][Web][极客大挑战 2019]EasySQL 1

    打开靶机对应的url 界面显示需要输入账号和密码 分别在两个输入框尝试加单引号尝试是否有sql注入的可能,比如 123' 发现两个框可以注入,因为报了个错误信息 You have an error i ...