注解系列——自定义注解验证器
本文实现自定义注解验证器,主要功能是: 1. 限定字段值只能是指定的几个值 2. 支持单值和多值验证 3. 验证过程中动态更改验证错误信息
自定义注解
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER}) @Retention(RUNTIME) @Documented @Constraint(validatedBy = { LimitedValidator.class}) public @interface Limited { String message() default "只能填写指定的值"; /** * 备选项 * @return */ int[] candidates(); /** * 枚举单值验证 * 多值验证为false 多值以逗号分隔 * @return */ boolean single() default true; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; }
指定验证器
/** * 枚举注解验证器 * * @author yuan * @since 2019-06-25 10:17 */ public class LimitedValidator implements ConstraintValidator<Limited, Object> { private Limited limitedAnno; @Override public boolean isValid(Object object, ConstraintValidatorContext context) { if (null == object) { return true; } String s = String.valueOf(object); List<String> list = new ArrayList<>(); if (limitedAnno.single()) { list.add(s); } else { String[] intStr = s.split(","); list = Arrays.asList(intStr); } Set<Integer> set = new HashSet<>(); L: for (String value : list) { for (int candidate : limitedAnno.candidates()) { if (!isInteger(value)) { // errorType for value return newErrorMsg(context, "类型不正确:" + value); } Integer parseInt = Integer.valueOf(value); if (candidate == parseInt) { set.add(parseInt); continue L; } } // no match for value return newErrorMsg(context, "不规范的输入:" + value); } if (list.size() != set.size()) { return newErrorMsg(context, "有重复值"); } return true; } @Override public void initialize(Limited constraintAnnotation) { this.limitedAnno = constraintAnnotation; } /** * 重新填充 error 信息 * * @param context * @param newErrorMsg */ private boolean newErrorMsg(ConstraintValidatorContext context, String newErrorMsg) { //禁用默认的message的值 context.disableDefaultConstraintViolation(); //重新添加错误提示语句 context.buildConstraintViolationWithTemplate(newErrorMsg) .addConstraintViolation(); return false; } /** * 是否是整数 * * @param s * @return */ private boolean isInteger(String s) { if (!StringUtils.isNumeric(s)) { return false; } try { Integer.valueOf(s); } catch (NumberFormatException e) { return false; } return true; } }
Bean对象
@Data public class PersonDO { @Limited(candidates = {1,2,5}) private Integer limit; @Limited(candidates = {1,2,5},single = false) private String multiStr; }
总结
-
自定义注解并指定验证器 实现验证器接口 ConstraintValidator 在bean上使用
BTW
可以写个统一的异常处理方法,处理验证结果
拓展
对 Spring Validation方法实现原理分析 感兴趣的小伙伴可以参考