基于自定义Validator来验证枚举类型
基于自定义Validator来验证枚举类型
一、背景
在我们系统中,有部分字段的值是枚举类型
的,但是请求参数中一般不会直接使用枚举来进行接收,而是使用Interget
等类型来接收,当系统中这些值是必须的时候,我们要保证前端系统传递的数据是正确的,合法的,因此需要进行校验。
例子:
比如:用户的性别 Sex
只能是 0-未知 1-男 2-女
,那么前端只能传递0,1,2
其中的一个,如果是别的值,则告知前端用户性别有问题。
二、技术要点
1、自己的验证逻辑类需要实现ConstraintValidator
接口。
2、自定义一个注解,注解上需要使用@Constraint(validatedBy = xxx)
,validatedBy的值指向验证的类,即实现了ConstraintValidator
接口的类。
三、实现一个自定义枚举校验。
1、需求。
我们有一个创建学生的接口,请求参数有一个 sex
值,它的值只能是0-未知 1-男 2-女
,在控制层基于自定义的枚举注解,验证 sex 的值是否合法。
2、实现步骤
1、自定义一个 Sex 枚举。
此枚举,主要用于记录 sex 属性的值可以是哪些值。
注意:
我们的 枚举类中的 code
的值,验证的时候需要用到这个。
@Getter
@AllArgsConstructor
public enum Sex {
UNKNOWN(0,"未知"),
MAN(1,"男"),
WOMEN(2,"女");
private final Integer code;
private final String desc;
}
2、自定义一个 Enum 注解
import com.google.common.collect.Lists;
import com.xincheng.common.exception.BizException;
import com.xincheng.xxcloud.ehouse.common.EhouseErrorCode;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
/**
* @author huan.fu 2021/4/1 - 下午3:35
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Constraint(validatedBy = EnumValidator.class)
public @interface Enum {
/**
* 枚举的类型
*/
Class<?> value();
/**
* 错误消息
*
* @return
*/
String message() default "枚举类型的值不正确";
/**
* 获取枚举值的方法
*/
String method() default "getCode";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
解释:
1、@Constraint(validatedBy = EnumValidator.class) 中的validatedBy指定的是 @Enum 这个注解交由那个类去校验。
2、Class<?> value() 表示需要这个字段对应的枚举的类型。
3、String method() default “getCode” 这个 method() 方法表示,我们怎么从具体的枚举对象中获取值。
比如上方定义的
Sex
,里面有2个属性code
和desc
,而code
作为枚举的值,此处的method() 就需要写getCode
。
3、编写具体的验证逻辑类
@Component
@Slf4j
class SpringBean {
public void invoked() {
log.info("调用spring管理的bean的方法");
}
}
/**
* 枚举校验
*/
@Slf4j
class EnumValidator implements ConstraintValidator<Enum, Object> {
// 存具体枚举的值
private final List<Object> values = Lists.newArrayList();
@Autowired
private SpringBean springBean;
@Override
public void initialize(Enum constraintAnnotation) {
springBean.invoked();
Class<?> enumClazz = constraintAnnotation.value();
Object[] enumConstants = enumClazz.getEnumConstants();
if (null == enumConstants) {
return;
}
Method method = BeanUtils.findMethod(enumClazz, constraintAnnotation.method());
if (null == method) {
log.warn("枚举对象:[{}]中不存在方法:[{}],请检查.", enumClazz.getName(), constraintAnnotation.method());
throw new BizException(EhouseErrorCode.FAIL.getCode(), "枚举对象中不存在获取值的方法");
}
method.setAccessible(true);
try {
for (Object enumConstant : enumConstants) {
values.add(method.invoke(enumConstant));
}
} catch (IllegalAccessException | InvocationTargetException e) {
log.warn("获取枚举类:[{}]的枚举对象的值失败.", enumClazz);
throw new BizException(EhouseErrorCode.FAIL.getCode(), "获取枚举值失败");
}
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
return null == value || values.contains(value);
}
}
注意:
1、ConstraintValidator<Enum, Object>
第一个参数:是我们自定义的校验注解,此处是 Enum,是因为我们上方自定义的注解就是 @interface Enum 。
第二个参数:指的是页面上传递过来的具体的数据的类型。
2、如果我们的LocalValidatorFactoryBean
是SpringConstraintValidatorFactory
,那么在我们的验证类中可以使用Spring的依赖注入。
3、isValid
方法需要保证线程安全,因为它可能是多线程调用。
4、编写一个web请求,添加学生。
1、创建请求参数实体类
@Data
public class Student {
@Enum(value = Sex.class, message = "请填写正确的心别")
private Integer sex;
}
注意:
1、sex
属性上使用了@Enum
来标识,表示后期需要使用@Enum这个来验证,而我们自己写的EnumValidator
是用来验证这个的。那么我们的sex
属性的值匹配上来哪些值是合法的呢,这个可以看到@Enum
的value上指定了value = Sex.class
,即我们的sex
的值需要是Sex
这个枚举类的值的其中一个。
2、编写访问方法
public String addStudent(@Valid @RequestBody Student student) {
log.info("student:[{}]", student);
return "ok";
}
3、页面访问
1、sex 属性的值在 Sex 枚举的范围之内
2、sex 属性的值不在 Sex 枚举的范围之内
四、对应关系
五、参考文档
基于自定义Validator来验证枚举类型的更多相关文章
- 实现自定义集合的可枚举类型(IEnumerable)和枚举数(IEnumerator )
下面的代码示例演示如何实现自定义集合的 IEnumerable 和 IEnumerator 接口: using System; using System.Collections; using Syst ...
- angular4 自定义表单验证Validator
表单的验证条件有时候满足不了需求就可以自定义验证 唯一要求返回是ValidatorFn export interface ValidatorFn{ (c:AbstractControl):Valida ...
- 自定义枚举类型的常用操作-附源码(xjl456852原创)
自定义枚举类型中,假如我们有name和desc这样的属性,并在这个基础上定义了多个对象. 那么就可能用到通过name获取desc,或者通过desc获取name.通过name或者desc获取对应的枚举对 ...
- mybatis-枚举类型的typeHandler&自定义枚举类型typeHandler
MyBatis内部提供了两个转化枚举类型的typeHandler给我们使用. org.apache.ibatis.type.EnumTypeHandler 是使用枚举字符串名称作为参数传递的 org. ...
- 基于struts2框架-自定义身份证号验证器
自定义拦截器的步骤: 1.定义一个验证器的类: > 自定义的验证器都需要实现 Validator接口. > 可以选择继承 ValidatorSupport 或 FieldValidato ...
- 自定义数据类型 C++ 结构体类型 共同体类型 枚举类型 类类型{}
一.结构体类型 结构体类型,共用体类型,枚举类型,类类型等统称为自定义类型(user-defined-type,UDT). 结构体相当于其他高级语言中的记录(record);例如: struct St ...
- 自定义fastjson对枚举类型的序列化及反序列化过程
通常,fastjson在序列化及反序列化枚举时,一般以下几种策略: 1).根据枚举的name值序列化及反序列化(默认) 2).根据枚举的ordinal序列化及反序列化 3).根据枚举的toString ...
- Oval框架如何校验枚举类型的一种思路
前言: Oval校验框架被广泛集成于各类接口参数校验中, 其方便的注解语法, 易读性和扩展性. 几乎成了java后端服务代码的标配. 有人会很疑惑, 都已经是枚举类型了, 还需要校验吗? 其实这边更确 ...
- 【转】Java基础笔记 – 枚举类型的使用介绍和静态导入--不错
原文网址:http://www.itzhai.com/java-based-notes-introduction-and-use-of-an-enumeration-type-static-impor ...
随机推荐
- python-request 实现企业微信接口自动化-1(DDT)
环境准备 python+requests 读取企业微信api开发文档,得知调用企业微信接口必须先获取企业微信的accesstoken是通过 ("corpid","&quo ...
- JS004. 获取数组最后一个元素且不改变数组的四种方法
TAG: Array.length Array.prototype.reverse() Array.prototype.slice() Array.prototype.pop() Array对象 - ...
- python生成时间序列(date_range)
介绍 自己写了一个用python内置模块实现的生成时间序列的函数 支持自动推断字符串到datetime的转换, 但对格式有一定要求, 其它格式可手动指定格式化方式, 格式化方式与python内置格式化 ...
- Spring Cloud Eureka 之常用配置解析
[原创内容,转载.引用请注明出处] 1. 配置项解析 1.1 通用配置 # 应用名称,将会显示在Eureka界面的应用名称列 spring.application.name=config-servic ...
- PTA——c++面向对象基础
1.结构不是面向对象的主要特征 2.每个 C++程序中都必须包含有这样一个函数,该函数的函数名为main 3.C++对C语言作了很多改进,下列描述中()使得C语言发生了质变,从面向过程变成了面向对象. ...
- mybatis一对多联表查询的两种常见方式
1.嵌套结果查询(部分代码如下) sql语句接上: 注释:class表(c别名),student表teacher(t别名)teacher_id为class表的字段t_id为teacher表的字段,因为 ...
- mysql 选取操作日志(mysql-bin.0000恢复数据)
my.ini 配置log-bin=mysql-bin 启用日志 用 mysql-bin.0000 mysqlbinlog -d keyboard ../data/mysql-bin.000024 – ...
- Java基础系列(37)- 数组下标越界及小结
数组的四个基本特点 其长度是确定的,数组一旦被创建,它的大小就是不可以改变的 其元素必须是相同类型,不允许出现混合类型 数组中的元素可以是任何数据类型,包括基本类型和引用类型 数组变量属于引用类型,数 ...
- Shell系列(26)- 条件判断之两个文件比较
两个文件之间进行比较 测试选项 作用 文件1 -net 文件2 判断文件1的修改时间是否比文件2的新(如果新则为真) 文件1 -ot 文件2 判断文件1的修改时间是否比文件2的旧(如果旧则为真) 文件 ...
- Jmeter压测学习3---通过正则表达式提取token
上一个随笔记录的是用json提取器提取token,这个随笔记录用正则表达式提取token 一.添加正则表达式 登录右击添加->后置处理器->正则表达式提取器 正则提取器参数说明: 要检查的 ...