当前位置: 首页 > backend >正文

校验枚举类类型的入参合法性的统一方案

文章目录

  • 背景
  • 解决
  • 实践
    • 定义枚举类 InEnum注解
    • 定义验证逻辑 InEnumValidator
  • 实际使用

背景

业务要做电商平台做入参, 在电商平台被抽离成枚举类的情况下 ,要怎么验证输入的参数是正确的呢?

解决

Constraint 实现自定义验证逻辑

@Constraint 注解用于标注其他注解,将其声明为验证约束。自定义约束注解需要指定一个或多个验证器实现类。
主要属性
validatedBy(): 指定实现约束验证逻辑的类(一个或多个)。这些类必须实现 ConstraintValidator 接口
message(): 定义默认的错误消息(通常使用 {} 占位符从资源文件中获取)
groups(): 允许指定验证分组
payload(): 可以附加到约束上的额外负载信息

实践

定义枚举类 InEnum注解

用来收纳验证用的基础信息, 包含要验证的枚举类,枚举类的取值方法, 报错提示

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;@Documented
@Constraint(validatedBy = {InEnumValidator.class})
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface InEnum {// 错误提示信息String message() default "必须在指定范围 {value}";// 分组Class<?>[] groups() default {};// 负载Class<? extends Payload>[] payload() default {};// 指定枚举类Class<? extends Enum<?>> enumClass();// 枚举中用于比较的方法名(默认为name())String enumMethod() default "name";// 是否忽略大小写boolean ignoreCase() default false;// 新增:是否在错误消息中显示所有合法值boolean showValues() default true;
}

定义验证逻辑 InEnumValidator

实现 ConstraintValidator接口

  1. initialize(A constraintAnnotation) 用于初始化验证器,用来获取InEnum注解上的数据
  2. isValid(T value, ConstraintValidatorContext context) 验证逻辑 true验证通过,false验证失败, 入参context处理错误信息, value 是要验证的对象
public class InEnumValidator implements ConstraintValidator<InEnum, Object> {/*** 枚举验证器实现类,用于验证输入值是否匹配指定枚举类中的值*/private Class<? extends Enum<?>> enumClass;      // 要验证的枚举类private String enumMethod;                       // 枚举类中用于获取值的方法名private boolean ignoreCase;                      // 是否忽略大小写进行验证private boolean showValues;                      // 验证失败时是否显示所有合法值private List<String> validValues = new ArrayList<>(); // 预加载的所有合法值列表/*** 初始化验证器* @param constraintAnnotation 包含验证配置的注解实例* @throws RuntimeException 如果初始化过程中发生反射相关异常*/@Overridepublic void initialize(InEnum constraintAnnotation) {enumClass = constraintAnnotation.enumClass();enumMethod = constraintAnnotation.enumMethod();ignoreCase = constraintAnnotation.ignoreCase();showValues = constraintAnnotation.showValues();// 通过反射获取枚举值并预加载到validValues集合中try {Method method = enumClass.getMethod(enumMethod);for (Enum<?> enumConstant : enumClass.getEnumConstants()) {Object value = method.invoke(enumConstant);if (value != null) {validValues.add(value.toString());}}} catch (Exception e) {throw new RuntimeException("无法初始化枚举验证器", e);}}/*** 验证输入值是否有效* @param value 要验证的输入值* @param context 验证上下文,用于自定义错误消息* @return true如果验证通过,false如果验证失败* @throws RuntimeException 如果验证过程中发生反射相关异常*/@Overridepublic boolean isValid(Object value, ConstraintValidatorContext context) {if (value == null) {return true;}try {Method method = enumClass.getMethod(enumMethod);// 遍历枚举值进行匹配验证for (Enum<?> enumConstant : enumClass.getEnumConstants()) {Object enumValue = method.invoke(enumConstant);if (enumValue == null) {continue;}// 根据ignoreCase设置进行不同方式的比较if (ignoreCase && value instanceof String && enumValue instanceof String) {if (((String) enumValue).equalsIgnoreCase((String) value)) {return true;}} else if (Objects.equals(enumValue, value)) {return true;}}// 验证失败时处理错误消息if (showValues) {String validValuesStr = validValues.stream().collect(Collectors.joining(", "));context.disableDefaultConstraintViolation();context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate().replace("{value}", validValuesStr)).addConstraintViolation();}return false;} catch (Exception e) {throw new RuntimeException(e);}}
}

实际使用

// 1.0 定义枚举类
@Getter
@AllArgsConstructor
public enum PlatformTypeEnum {/*** 未来支持的平台很多,但是现在只支持抖音* */DY(1, "dy", "抖音"),;private final Integer value;private final String code;private final String name;public String getCode(){return code;}
}// 2.0 验证入参
@Data
public class CrowdReqVO {@NotNull(message = "抖音号不能为空")@ApiModelProperty("抖音号")private String awemeId;@DateTimeFormat(pattern = "yyyy-MM-dd")@ApiModelProperty("查询日期,格式:yyyy-MM-dd")@NotNull(message = "查询日期不能为空")private LocalDate searchDate;@ApiModelProperty("直播间类型:dy-抖音;ks-快手;sph-视频号")@NotEmpty(message = "请输入平台类型")@InEnum(enumClass = PlatformTypeEnum.class, enumMethod = "getCode", message = "平台类型必须在指定范围: {value}")private String platformType;
}
http://www.xdnf.cn/news/13340.html

相关文章:

  • 基于算法竞赛的c++编程(28)结构体的进阶应用
  • DP 1.4 to HDMI 2.1 (DSC) ,8k@60Hz
  • 【WebRTC-14】webrtc是如何创建视频的软/硬编码器?
  • AR 珠宝佩戴,突破传统的购物新体验​
  • visual studio 2022更改主题为深色
  • 学校招生小程序源码介绍
  • Web安全漏洞详解及解决方案
  • LarkXR 赋能AI x XR数字供应链:引领智能设计、数字孪生与零售新未来
  • Android 中使用 OkHttp 创建多个 Client
  • NLP学习路线图(三十七): 问答系统
  • 数据工程全景指南:从基础概念到最佳实践
  • 多面体编译,具体操作模式
  • 使用 origin -> master 强制覆盖本地 master
  • 蜗牛TV_PTV-8608_GK6323V100A-原机备份
  • Everything配置优化指南:打造最快文件搜索工具
  • 手写muduo网络库(二):文件描述符fd及其事件的封装(Channel类的实现)
  • 第十章、无线通信之红外遥控协议NEC及红外接收模块驱动的构建
  • 洛谷P1923 【深基9.例4】求第 k 小的数
  • 【SQL学习笔记2】深入理解 CASE WHEN 的魔法用法
  • 可视化在车间质量管控中的创新应用,提升品质
  • python模拟键盘 鼠标操作 通过ctypes调用Windows API实现底层输入模拟
  • filebeat原理架构
  • css~word-break属性
  • 核方法、核技巧、核函数、核矩阵
  • 模型训练-关于token【低概率token, 高熵token】
  • 【Python】 -- 趣味代码 - 飞船大战游戏
  • DiffBP: generative diffusion of 3D molecules for target protein binding
  • 智慧园区综合运营管理平台(SmartPark)和安全EHS平台的分工与协作
  • 电动汽车VCU扭矩控制模式分类方法
  • 【javascript】泡泡龙游戏中反弹和查找匹配算法