Java自定义注解校验枚举值类型参数
项目开发中会经常使用到各种枚举值,枚举值一般都是固定的,不会随意改变其中的值。
比如性别分为男女,确定之后一般都不会轻易改变,这时候使用枚举值就非常地方便。很多
时候,在页面中传入的参数就是枚举值中的一个,比如性别,或者是星期,月份,以及自定义
的各种类型等等。如果是手动校验就非常麻烦,假如有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自定义注解校验枚举值类型参数的更多相关文章
- Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性)
Java自定义注解源码+原理解释(使用Java自定义注解校验bean传入参数合法性) 前言:由于前段时间忙于写接口,在接口中需要做很多的参数校验,本着简洁.高效的原则,便写了这个小工具供自己使用(内容 ...
- Java 自定义注解 校验指定字段对应数据库内容重复
一.前言 在项目中,某些情景下我们需要验证编码是否重复,账号是否重复,身份证号是否重复等... 而像验证这类代码如下: 那么有没有办法可以解决这类似的重复代码量呢? 我们可以通过自定义注解校验的方式去 ...
- java自定义注解实现前后台参数校验
2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...
- java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题
一.java自定义注解相关知识 注解这东西是java语言本身就带有的功能特点,于struts,hibernate,spring这三个框架无关.使用得当特别方便.基于注解的xml文件配置方式也受到人们的 ...
- Java自定义注解和运行时靠反射获取注解
转载:http://blog.csdn.net/bao19901210/article/details/17201173/ java自定义注解 Java注解是附加在代码中的一些元信息,用于一些工具在编 ...
- java自定义注解类
一.前言 今天阅读帆哥代码的时候,看到了之前没有见过的新东西, 比如java自定义注解类,如何获取注解,如何反射内部类,this$0是什么意思? 于是乎,学习并整理了一下. 二.代码示例 import ...
- java自定义注解注解方法、类、属性等等【转】
http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...
- JAVA自定义注解 ------ Annotation
日常开发工作中,合理的使用注解,可以简化代码编写以及使代码结构更加简单,下面记录下,JAVA自定义注解的开发过程. 定义注解声明类. 编写注解处理器(主要起作用部分). 使用注解. 相关知识点介绍, ...
- Java自定义注解的实现
Java自定义注解的实现,总共三步(eg.@RandomlyThrowsException): 1.首先编写一个自定义注解@RandomlyThrowsException package com.gi ...
- java 自定义注解以及获得注解的值
1.自定义注解 import java.lang.annotation.*; @Documented @Target(ElementType.FIELD) @Inherited @Retention( ...
随机推荐
- Vite4+Typescript+Vue3+Pinia 从零搭建(2) - ts配置
项目代码同步至码云 weiz-vue3-template 关于tsconfig的配置字段可查看其他文档,如 typeScript tsconfig配置详解 tsconfig.json 文件修改如下: ...
- 进程状态|操作系统|什么是pcb|什么是僵尸进程 |什么是孤儿进程 【超详细的图文解释】【Linux OS】
说在前面 今天给大家带来操作系统中进程状态的详解. 本篇博主将通过从进程状态的广泛概念,深入到Linux操作系统详细的一些进程状态.在解释进程状态的过程中,博主还会穿插一些操作系统一些重要概念!本篇干 ...
- Android Graphics 显示系统 - 如何模拟多(物理)显示屏?
" 本着花小钱办大事,不花钱也办事的原则,为了避免花钱买设备,那如何更便捷地学习/测试Android多屏显示的内容呢?本文就给大家介绍一种模拟Android多个物理屏幕显示的方法." ...
- shell 两个数组比较,得到元素的并集、交集等
linux shell 实现数组比较,取元素的并集.交集时,可以使用sort排序.uniq统计和awk数据过滤. shell 实现如下 file_list_1=("test1" & ...
- 6.用户输入和 while 循环--《Python编程:从入门到实践》
6.1 input 函数 函数input()接受一个参数:即要向用户显示的提示或说明.input 将用户输入解释为字符串. name = input("Please enter your n ...
- Linux中单引号和双引号的区别
区别:单引号属于强引用,它会忽略所有被引起来的字符的特殊处理,被引用起来的字符会被原封不动的使用:而双引号属于弱引用,它会对一些被引起来的字符进行特殊处理.简单来说,单引号直接输出内部字符串,不解析特 ...
- NC19246 数据结构
题目链接 题目 题目描述 qn姐姐最好了~ qn姐姐给你了一个长度为n的序列还有m次操作让你玩, 1 l r 询问区间[l,r]内的元素和 2 l r 询问区间[l,r]内的元素的平方和 3 l r ...
- HTTP协议发展历程
HTTP协议发展历程 HTTP超文本传输协议是一个用于传输超文本文档的应用层协议,它是为Web浏览器与Web服务器之间的通信而设计的,HTTP协议到目前为止全部的版本可以分为HTTP 0.9.HTTP ...
- Java实现文件下载断点续传(一)
参考文章:https://www.ibm.com/developerworks/cn/java/joy-down/ 1.原理介绍 想象一下我们下载一个10G的文件,当下载到9.99G的时候断网了... ...
- JVM之直接内存与非直接内存
直接内存 直接内存:概指系统内存,而非堆内存,不指定大小时它的大小默认与堆的最大值-Xmx参数值一致. 非直接内存: 也可以称之为堆内存,运行JVM都会预先分配一定内存,我们把JVM管理的这些内存称为 ...