1. 使用场景2. 技术实现
2.1 实现思路2.2 代码实现
2.2.1 引入依赖2.2.2 自定义校验注解2.2.3 校验工具类2.2.4 校验处理逻辑 3. 使用示例
1. 使用场景2. 技术实现 2.1 实现思路例如:当属性condition=1时,某某参数为必填;某某参数为必填且只能为某些值或不能为某些值。
支持扩展场景:只允许填入某些值不允许填入某些值如果使用注解的属性是对象,可以控制是否对对象中的属性进行再校验
使用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.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Repeatable(OtherAffect.List.class) @Constraint(validatedBy = {OtherAffectValidator.class}) public @interface OtherAffect { String column(); String[] columnValue(); String[] allowedValues() default { }; String[] notAllowedValues() default { }; String message() default ""; boolean isCheck() default false; Class>[] groups() default { }; Class extends Payload>[] payload() default { }; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface List { OtherAffect[] 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 OtherAffectValidator implements ConstraintValidator3. 使用示例{ private String[] columnValue; private String column; private boolean isCheck; private String[] allowedValues; private String[] notAllowedValues; private static Validator validator; @Override public void initialize(OtherAffect constraintAnnotation) { columnValue = constraintAnnotation.columnValue(); column = constraintAnnotation.column(); isCheck = constraintAnnotation.isCheck(); allowedValues = constraintAnnotation.allowedValues(); notAllowedValues = constraintAnnotation.notAllowedValues(); // 获取校验Validator ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); factory.close(); } @Override public boolean isValid(Object o, ConstraintValidatorContext context) { // 获取column的请求值,为空的话校验失败 String columnRequestValue = getColumnRequestValue(); if (StrUtil.isBlank(columnRequestValue)) { return ValidatorUtils.getResult(StrUtil.format("请求值{}不能为空", column), context); } // 如果column的值存在于columnValue中 if (Arrays.asList(columnValue).contains(columnRequestValue)) { // 被注解字段的值为空直接校验不通过 if (ObjectUtil.isEmpty(o)) { return false; } // notAllowedValues、allowedValues存在情况 boolean b = (notAllowedValues != null && notAllowedValues.length > 0) || (allowedValues != null && allowedValues.length > 0); if (b) { String validResult = ValidatorUtils.validatevalues(allowedValues, notAllowedValues, o); return ValidatorUtils.getResult(validResult, context); } // 如果开启校验 if (isCheck) { return validObject(o, context); } } return true; } private String getColumnRequestValue(){ String paramValue = ServletUtils.getParameter(column); // 如果从param获取不到,再找body if(StringUtils.isBlank(paramValue)){ HttpServletRequest request = ServletUtils.getRequest(); // 获取column请求参数值 String body = ServletUtil.getBody(request); if(StrUtil.isNotBlank(body)){ JSONObject jsonObject = JSONUtil.parseObj(body); paramValue = String.valueOf(jsonObject.get(column)); } } return paramValue; } private boolean validObject(Object o, ConstraintValidatorContext context){ // 定义错误信息 StringBuffer errorMsg = new StringBuffer(); boolean result = true; // 当被注解属性为列表时 if(o instanceof ArrayList>){ List >> collect = new ArrayList<>(); for (Object oItem : (List>) o){ Set > constraintViolations = validator.validate(oItem); collect.add(constraintViolations); } result = getListResult(collect); ValidatorUtils.getListInfo(errorMsg, collect); }else { // 当被注解属性为单个对象时 Set > constraintViolations = validator.validate(o); result = constraintViolations.isEmpty(); ValidatorUtils.getOneInfo(errorMsg, constraintViolations); } // 把自定义返回错误信息写入上下文 if(!result){ context.disableDefaultConstraintViolation(); context.buildConstraintViolationWithTemplate(errorMsg.toString()) .addConstraintViolation(); } return result; } private boolean getListResult(List >> collect){ boolean result = true; for (Set > constraintViolations : collect) { result = constraintViolations.isEmpty(); } return result; }
@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; @OtherAffect(column = "type", columnValue = {"2", "3", "4"}, message = "父id不能为空", groups = { AddGroup.class, EditGroup.class }) private Long parentId; }
解释:
当传入的type值为2、3、4时,这个父id传入值不能为空
其他扩展用法,有兴趣可以复制代码尝试!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)