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

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

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

的各种类型等等。如果是手动校验就非常麻烦,假如有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. 解决:VScode中 import 后出现no module的问题

    问题: ModuleNotFoundError: No module named 'xxx' 除去没有安装包的问题 这个问题还是挺难受的,pycharm和终端都可以运行,只有vscode报错 方法一: ...

  2. 9.3 Windows驱动开发:内核解析PE结构节表

    在笔者上一篇文章<内核解析PE结构导出表>介绍了如何解析内存导出表结构,本章将继续延申实现解析PE结构的PE头,PE节表等数据,总体而言内核中解析PE结构与应用层没什么不同,在上一篇文章中 ...

  3. blazor maui hybrid app显示本地图片

    啊... ... 一通操作下来感觉就是两个字 折磨 跨平台有跨平台的好处 但框架本身支持的有限 很多东西做起来很曲折 哎 这里总结一下笔者为了折腾本地图片显示的尝试 为什么要做本地图片展示呢 如果是做 ...

  4. KB0001.修改DoraCloud管理系统的IP地址

    KB0001.修改DoraCloud管理系统的IP地址 DoraCloud 管理系统是一个CentOS Linux的虚拟机.我们既可以通过DoraCloud后台管理系统修改它的IP地址,也可以通过Ce ...

  5. ElasticSearch7.3学习(三)----采用restful风格 批量(bulk)增删改

    Bulk 操作是将文档的增删改查一些列操作,通过一次请求全都做完.目的是减少网络传输次数. 语法: POST /_bulk {"action": {"metadata&q ...

  6. Spring 与 Mybatis 中的 @Repository 与 @Mapper

    @Repository.@Service.@Controller,它们分别对应存储层Bean,业务层Bean,和展示层Bean.如果使用@Repository则需要使用@MapperScan(&quo ...

  7. 到什么程度才叫精通 Linux?

    大家好,我是陶朱公Boy,一个认真生活,总想超越自己的程序员. 前言 知乎上有一个提问:到什么程度才叫精通 Linux?                              ↓↓↓ 今天,我们就 ...

  8. JS leetcode 买卖股票的最佳时机 题解分析,我离职了。

    壹 ❀ 引 昨天下班后,还是找经理提出了辞职,没有犹豫的裸辞,今天与人事的对话不小心被后台的同事听到,一下在公司传开了,下午我与同事们多人对线,被他们的消息轰炸....没错,我真的要走了. 因为什么原 ...

  9. Elasticsearch Web管理工具

    Cerebro是一个开源的elasticsearch web管理工具 首先,下载Elasticsearch https://www.elastic.co/guide/en/elasticsearch/ ...

  10. 文件的拓展及文件函数,定义函数及函数参数---day09

    1.文件的拓展模式 utf-8 编码格式下,默认一个中文三个字节,一个英文或符号占用一个字节 read() 功能:读取字符的个数(里面的参数代表字符个数) seek() 功能:调整指针的位置(里面的参 ...