自定义校验注解实现ConstraintValidator

10 篇文章 0 订阅
10 篇文章 0 订阅

一、步骤

1.创建自定义注解 IdCard

  • @Constraint指定校验类。
  •  除了自定义的message、require属性外,下面的groups和payload也是必须添加的。
/**
 * 用于校验身份证的注解
 */
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = IdCardValidator.class)//指定校验类
public @interface IdCard {

    boolean required() default true;

    String message() default "身份证格式错误";

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

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

2.创建注解校验类 IdCardValidator

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

public class IdCardValidator implements ConstraintValidator<IdCard,String> {
    
    private boolean required = false;

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

    @Override
    public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
        if (required){
            return IdentityCardNumberUtil.isValaid(value);
        }else{
            if (StringUtil.isEmpty(value)){
                return true;
            }else {
                return IdentityCardNumberUtil.isValaid(value);
            }
        }
    }
}

3.创建用户实体类 User

  • 在IdCard属性添加了自定义注解
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {

    private static final long serialVersionUID = -53183535344760589L;

    private String id;

    private String name;

    @IdCard
    private String IdCard;

}

4.创建全局异常捕获类 GlobalExceptionHandler

  • 在valid校验中,如果校验不通过,会产生BindException异常,这边进行全局异常捕获
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 系统内部异常
     *
     * @param e Exception
     * @return Result
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String handleException(Exception e) {
        log.error("系统内部异常,异常信息:", e);
        return "系统异常,请联系管理人员";
    }

    /**
     * BindException
     *
     * @param e BindException
     * @return Result
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String BindException(Exception e) {
        log.error("身份证校验异常:", e);
        return "身份证校验失败";
    }
}

5.创建工具类utils

//身份证utils
public final class IdentityCardNumberUtil {

    private IdentityCardNumberUtil() {
    }

    public static boolean isValaid(String idNumber) {
        if (StringUtil.isEmpty(idNumber)) {
            return false;
        } else {
            boolean matches = idNumber.matches("\\d{6}(19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]");
            if (!matches) {
                return false;
            } else {
                String verifyCode = getVerifyCode(idNumber).toLowerCase();
                return verifyCode.equals(idNumber.substring(idNumber.length() - 1).toLowerCase());
            }
        }
    }

    private static String getVerifyCode(String idNumber) {
        int sum = 0;

        for(int i = 0; i < 17; ++i) {
            int k = (int)Math.pow(2.0D, (double)(17 - i));
            byte weight = (byte)(k % 11);
            sum += Integer.parseInt(idNumber.substring(i, i + 1)) * weight;
        }

        byte mode = (byte)(sum % 11);
        return "10X98765432".substring(mode, mode + 1);
    }
}

//字符串utils
public final class StringUtil {
    private StringUtil() {
    }

    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }

}

 6.编写测试类

  • 加上@Valid注解开启valid校验。
@RestController
public class TestController {
    @GetMapping("/valid")
    public String isValid(@Valid  User user){
        return "校验成功";
    }
}

7.执行结果

  • 输入正确的身份证号码,返回检验成功

  •  输入错误的身份证号码,返回身份证校验失败

 8.示例代码

        https://gitee.com/chaoren_me/ConstraintValidatorDemo.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值