1. 使用场景2. 技术实现
2.1 实现思路2.2 代码实现
2.2.1 引入依赖2.2.2 自定义校验注解2.2.3 校验工具类2.2.4 校验处理逻辑 3. 使用示例
1. 使用场景2. 技术实现 2.1 实现思路某接口的入参某属性,只希望为系统中某枚举的中定义过的值。
例如:用户类型枚举中定义 10-普通用户 20-管理员 30-游客 40-中级用户 50-高级用户
希望某接口的入参 userType 只能填入这几种type
支持扩展场景:只允许填入枚举中定义过的某些值不允许填入某些值
使用Hibernate Validator校验工具,自定义校验注解及其校验逻辑。
Hibernate Validator官方文档:
https://docs.jboss.org/hibernate/validator/7.0/reference/en-US/html_single/#validator-gettingstarted
2.2.2 自定义校验注解org.springframework.boot spring-boot-starter-validation
@Target({ElementType.PARAMETER, ElementType.FIELD}) @Retention(RUNTIME) @Repeatable(VerifyEnum.List.class) @Constraint(validatedBy = {EnumValidator.class}) public @interface VerifyEnum { Class extends Enum>> enumClass(); String keyColumn(); String[] allowedValues() default { }; String[] notAllowedValues() default { }; String message() default ""; Class>[] groups() default { }; Class extends Payload>[] payload() default {}; @Target({ElementType.PARAMETER, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface List { VerifyEnum[] value(); } }2.2.3 校验工具类
public class ValidatorUtils { private static ValidatorFactory factory; public static Validator validator; public static Executablevalidator executablevalidator; static { initValidator(); clean(); } public static void initValidator() { factory = Validation.byProvider(Hibernatevalidator.class) .configure() .failFast(true) .buildValidatorFactory(); validator = factory.getValidator(); } public static void initExecutablevalidator() { factory = Validation.buildDefaultValidatorFactory(); executablevalidator = factory.getValidator().forExecutables(); } public static void clean() { factory.close(); } public static2.2.4 校验处理逻辑Set > validMethod(T t, Method method, Object[] parameterValues){ return executablevalidator.validateParameters(t, method, parameterValues); } public static void validateObject(Object object, Class>... groups) { Set > constraintViolations = validator.validate(object, groups); if(CollectionUtil.isNotEmpty(constraintViolations)){ String errorMsg = StrUtil.format("对象{}校验异常:{}", object.getClass().getSimpleName(), getErrorMsg(constraintViolations)); throw new ApiException(ResultEnum.PARAMETER_VERIFICATION_FAIL.getCode(), errorMsg); } } public static void validateObjectList(List
public class EnumValidator implements ConstraintValidator3. 使用示例{ private Class extends Enum>> enumClass; private String[] allowedValues; private String[] notAllowedValues; private String keyColumn; @Override public void initialize(VerifyEnum constraintAnnotation) { enumClass = constraintAnnotation.enumClass(); allowedValues = constraintAnnotation.allowedValues(); notAllowedValues = constraintAnnotation.notAllowedValues(); keyColumn = constraintAnnotation.keyColumn(); } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { if(value != null){ // 校验enumClass中是否存在keyColumn字段 if(!ReflectUtil.hasField(enumClass, keyColumn)){ throw new RuntimeException(StrUtil.format("EnumValidator:<{}>中不存在填入的<{}>字段", enumClass.getSimpleName(), keyColumn)); } // 获取所有该枚举的指定字段的值列表 List codevalues = EnumUtil.getFieldValues(enumClass, keyColumn); String validatevalueMsg = ValidatorUtils.validatevalues(allowedValues, notAllowedValues, value, codevalues); if(StrUtil.isNotBlank(validatevalueMsg)){ return ValidatorUtils.getResult(validatevalueMsg, context); }else{ return true; } } return true; } }
枚举类
public enum SysDeptTypeEnum { SCHOOL(1, "学校"), INVALID(2, "单位/学院"), DEPARTMENT(3, "部门"), MAJOR(4, "专业"), ; private final int code; private final String name; SysDeptTypeEnum(int code, String info) { this.code = code; this.name = info; } public static String getValue(int code) { SysDeptTypeEnum[] enums = values(); for (SysDeptTypeEnum item : enums) { if (item.code == code) { return item.getName(); } } return null; } public int getCode() { return code; } public String getName() { return name; } }
DTO请求参数实体类
@Data public class SysDeptDto { @NotNull(message = "组织架构Id不能为空", groups = { EditGroup.class }) private Long deptId; @NotNull(message = "组织架构类别不能为空", groups = { AddGroup.class, EditGroup.class }) @VerifyEnum(enumClass = SysDeptTypeEnum.class, keyColumn = "code", groups = { AddGroup.class, EditGroup.class }) private Integer type; // 其他属性省略... }
Controller接口
@PostMapping() public ApiResultadd(@Validated(AddGroup.class) @RequestBody SysDeptDto dto){ return toApiRes(sysDeptService.insertByDto(dto)); }
请求测试
稍微修改下注解代码
@VerifyEnum(enumClass = SysDeptTypeEnum.class, keyColumn = "code", notAllowedValues = {"5"}, groups = { AddGroup.class, EditGroup.class })
测试:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)