
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 static 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
2.2.4 校验处理逻辑
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 ApiResult add(@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条)