通过实现ConstraintValidator完成自定义校验注解

首先贴上代码

/**
 * @author hsw
 * @Date 11:28 2018/7/26
 */
@Data
public class LoginVO {
    @NotNull
    @IsMobile
    private String mobile;

    @NotNull
    @Length(min = 32)
    private String password;

}
/**
 * @author hsw
 * @Date 16:55 2018/7/26
 */
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {

    private boolean require = false;

    @Override
    public void initialize(IsMobile constraintAnnotation) {
        require = constraintAnnotation.required();
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if(require){
            return ValidatorUtils.isMobile(s);
        }else {
           if (StringUtils.isEmpty(s)) {
               return true;
           }else {
               return ValidatorUtils.isMobile(s);
           }
        }
    }
}
/**
 * @author hsw
 * @Date 16:54 2018/7/26
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(
        validatedBy = {IsMobileValidator.class}
)
public @interface IsMobile {

    boolean required() default true;

    String message() default "手机号格式不正确";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    
}
public class ValidatorUtils {

    private static final Pattern mobile_pattern = Pattern.compile("1\\d{10}");

    public static boolean isMobile(String src) {
        if (StringUtils.isEmpty(src)) {
            return false;
        }
        Matcher m = mobile_pattern.matcher(src);
        return m.matches();
    }
}
  1. LoginVO类为一个普通的实体类,其中的mobile属性添加了自定义注解。
  2. IsMobile类为自定义的字段注解,未了解过注解的同学请自行百度,在此不做基础介绍。该自定义注解类中用到了四种元注解,最后一个@Constraint指定了校验类,也就是接下来的IsMobileValidator类。值得一提的是除了自定义的message、require属性外,下面的groups和payload也是必须添加的。
  3. ValidatorUtils为一个工具类,简单校验了是否为手机号,没有了解过的可以看我之前的一篇博文:https://blog.csdn.net/qq_38439885/article/details/80230753
  4. IsMobileValidator为自定义注解的校验类。

校验类需要实现ConstraintValidator接口。
接口使用了泛型,需要指定两个参数,第一个自定义注解类,第二个为需要校验的数据类型。
实现接口后要override两个方法,分别为initialize方法和isValid方法。其中initialize为初始化方法,可以在里面做一些初始化操作,isValid方法就是我们最终需要的校验方法了。可以在该方法中实现具体的校验步骤。本示例中进行了简单的手机号校验。

完成这几部分之后,一个简单的自定义校验注解就完成啦,不要忘记在使用的时候加上@Valid注解开启valid校验。

那么如何获取在注解中定义的message信息呢?

在valid校验中,如果校验不通过,会产生BindException异常,捕捉到异常后可以获取到defaultMessage也就是自定义注解中定义的内容,具体实现如下:

    BindException ex = (BindException)e;
    List<ObjectError> errors = ex.getAllErrors();
    ObjectError error = errors.get(0);
    String msg = error.getDefaultMessage();

本文仅供学习记录使用。欢迎交流。

  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
好的,以下是一个自定义注解校验身份证的代码示例: 首先,我们需要定义一个注解 `@IdNumber`,用于标注需要进行身份证校验的字段: ```java @Documented @Constraint(validatedBy = IdNumberValidator.class) @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface IdNumber { String message() default "身份证号码不正确"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } ``` 其中,`@Constraint(validatedBy = IdNumberValidator.class)` 表示该注解需要使用 `IdNumberValidator` 进行校验。 接着,我们需要实现 `IdNumberValidator`: ```java public class IdNumberValidator implements ConstraintValidator<IdNumber, String> { @Override public void initialize(IdNumber constraintAnnotation) { } @Override public boolean isValid(String value, ConstraintValidatorContext context) { if (StringUtils.isBlank(value)) { return true; } return isIdNumber(value); } /** * 身份证校验 * * @param idNumber 身份证号码 * @return 是否有效 */ private boolean isIdNumber(String idNumber) { String regex = "^\\d{15}$|^\\d{17}[0-9Xx]$"; if (!idNumber.matches(regex)) { return false; } String provinceCode = idNumber.substring(0, 2); if (!ProvinceCodeUtils.isValidProvinceCode(provinceCode)) { return false; } if (!isValidBirthDate(idNumber)) { return false; } return isValidCheckCode(idNumber); } /** * 校验生日日期 * * @param idNumber 身份证号码 * @return 是否有效 */ private boolean isValidBirthDate(String idNumber) { String birthDateStr; if (idNumber.length() == 15) { birthDateStr = "19" + idNumber.substring(6, 12); } else { birthDateStr = idNumber.substring(6, 14); } SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd"); format.setLenient(false); try { format.parse(birthDateStr); } catch (ParseException e) { return false; } return true; } /** * 校验校验码 * * @param idNumber 身份证号码 * @return 是否有效 */ private boolean isValidCheckCode(String idNumber) { if (idNumber.length() == 15) { return true; } char[] idCharArray = idNumber.toCharArray(); int[] idIntArray = new int[17]; for (int i = 0; i < 17; i++) { idIntArray[i] = Integer.parseInt(String.valueOf(idCharArray[i])); } int[] weightFactorArray = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; int sum = 0; for (int i = 0; i < 17; i++) { sum += idIntArray[i] * weightFactorArray[i]; } int checkCodeIndex = sum % 11; char[] checkCodeArray = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; char checkCode = checkCodeArray[checkCodeIndex]; return checkCode == idCharArray[17]; } } ``` 其中,`isValid` 方法用于进行身份证校验,`isValidBirthDate` 方法用于校验生日日期,`isValidCheckCode` 方法用于校验校验码。 最后,在需要进行身份证校验的字段上使用 `@IdNumber` 注解即可: ```java public class User { @IdNumber private String idNumber; // getter/setter 略 } ``` 这样,在使用 `@Valid` 注解校验实体时,如果 `idNumber` 字段不符合身份证规则,则会抛出 `ConstraintViolationException` 异常。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值