身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑)

这篇具有很好参考价值的文章主要介绍了身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目标

自定义一个用于校验 身份证号码 格式的注解@IdCard,能够和现有的 Validation 参数校验机制兼容,使用方式和其他校验注解保持一致(使用 @Valid 注解接口参数)。

本文使用原生方式实现校验逻辑,校验规则的实现较为基础;Hutool工具提供了更加完善的校验工具,可以考虑使用其来实现校验逻辑。

使用 Hutool 身份证号码格式校验工具,实现校验逻辑,参考博客如下:
《身份证号码,格式校验:@IdCard(Validation + Hutool)》

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验

校验逻辑

有效格式

符合国家标准。

公民身份号码按照GB11643-1999《公民身份号码》国家标准编制,由18位数字组成:前6位为行政区划代码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。

严格校验

本文采用的校验方式,采用严格校验,第18位校验码,只能为数字大写X小写x无法通过校验。

不校验非空

身份证号码注解,校验的是格式;不校验是否为空(null 或 空字符串)。如果身份证号码为空,此注解校验是可以通过的;

是否校验非空,要根据业务逻辑来确定;如果业务逻辑需要校验非空,则使用注解 @NotEmpty

核心代码

需要定义的内容包含三个部分:

  1. 注解@IdCard
  2. 校验器IdCardValidator
  3. 校验工具类 IdCardUtil

注解:@IdCard

package com.example.core.validation.idcard;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * 身份证号码。字符串必须是格式正确的身份证号码。
 * <p>
 * {@code null} 或 空字符串,是有效的(能够通过校验)。
 * <p>
 * 支持的类型:字符串
 *
 * @author songguanxun
 * @since 1.0
 */
@Target({FIELD})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {

    /**
     * @return the error message template
     */
    String message() default "身份证号码,格式错误";

    /**
     * @return the groups the constraint belongs to
     */
    Class<?>[] groups() default {};

    /**
     * @return the payload associated to the constraint
     */
    Class<? extends Payload>[] payload() default {};

}

校验器:IdCardValidator

package com.example.core.validation.idcard;

import com.example.core.util.IdCardUtil;
import org.springframework.util.ObjectUtils;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

/**
 * 身份证号码,格式校验器
 */
public class IdCardValidator implements ConstraintValidator<IdCard, String> {

    @Override
    public void initialize(IdCard constraintAnnotation) {
        ConstraintValidator.super.initialize(constraintAnnotation);
    }


    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (ObjectUtils.isEmpty(value)) {
            return true;
        }

        return IdCardUtil.isValid(value);
    }

}

校验工具类

package com.example.core.util;

/**
 * 身份证号码,校验工具类
 */
public class IdCardUtil {

    // 每位加权因子
    private static final int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};


    /**
     * 是格式正确的身份证号码
     */
    public static boolean isValid(String idCard) {
        // null ,为假
        if (idCard == null) {
            return false;
        }

        // 非18位,为假
        if (idCard.length() != 18) {
            return false;
        }

        // 获取前17位
        String idCard17 = idCard.substring(0, 17);
        // 获取第18位
        String idCard18Code = idCard.substring(17, 18);

        // 前17位,不全部为数字,为假
        if (!isDigital(idCard17)) {
            return false;
        }

        char[] c = idCard17.toCharArray();

        int[] bit = convertCharToInt(c);
        int sum17 = getPowerSum(bit);
        // 将和值与11取模得到余数进行校验码判断
        String checkCode = getCheckCodeBySum(sum17);
        if (null == checkCode) {
            return false;
        }
        // 将身份证的第18位,与算出来的校码进行匹配,不相等就为假
        return idCard18Code.equals(checkCode);
    }


    /**
     * 数字验证
     */
    private static boolean isDigital(String str) {
        return str != null && !str.isEmpty() && str.matches("^[0-9]*$");
    }


    /**
     * 将字符数组转为整型数组
     */
    private static int[] convertCharToInt(char[] c) throws NumberFormatException {
        int[] a = new int[c.length];
        int k = 0;
        for (char temp : c) {
            a[k++] = Integer.parseInt(String.valueOf(temp));
        }
        return a;
    }


    /**
     * 将身份证的每位和对应位的加权因子相乘之后,再得到和值
     */
    private static int getPowerSum(int[] bit) {
        if (power.length != bit.length) {
            return 0;
        }

        int sum = 0;
        for (int i = 0; i < bit.length; i++) {
            for (int j = 0; j < power.length; j++) {
                if (i == j) {
                    sum = sum + bit[i] * power[j];
                }
            }
        }
        return sum;
    }


    /**
     * 将和值与11取模得到余数进行校验码判断
     *
     * @return 校验位
     */
    private static String getCheckCodeBySum(int sum17) {
        String checkCode = null;
        switch (sum17 % 11) {
            case 10:
                checkCode = "2";
                break;
            case 9:
                checkCode = "3";
                break;
            case 8:
                checkCode = "4";
                break;
            case 7:
                checkCode = "5";
                break;
            case 6:
                checkCode = "6";
                break;
            case 5:
                checkCode = "7";
                break;
            case 4:
                checkCode = "8";
                break;
            case 3:
                checkCode = "9";
                break;
            case 2:
                checkCode = "X";
                break;
            case 1:
                checkCode = "0";
                break;
            case 0:
                checkCode = "1";
                break;
        }
        return checkCode;
    }

}

使用

@IdCard 放在需要校验格式的 身份证号码 字段上。

package com.example.web.response.model.param;

import com.example.core.validation.idcard.IdCard;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

@Data
@Schema(name = "新增用户Param")
public class UserAddParam {
    
    // 其他字段

    @IdCard
    @Schema(description = "身份证号码", example = "110101202301024130")
    private String idCard;

}

校验效果

校验工具类,单元测试

package com.example;

import com.example.core.util.IdCardUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

@Slf4j
public class IdCardTest {

    @Test
    void test() {
        test("110101202301024130");
        test("11010120230102857X");
        test("11010120230102857x");
        test("110101202301024130啊啊啊啊");
    }


    private void test(String idCard) {
        log.info("是否为身份证号码格式:{} = {}", idCard, IdCardUtil.isValid(idCard));
    }

}

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验

接口测试

校验结果为 成功

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验
身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验

校验结果为 失败

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验

身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑),接口参数校验,spring boot,接口参数校验文章来源地址https://www.toymoban.com/news/detail-726362.html

到了这里,关于身份证号码,格式校验:@IdCard(Validation + 原生实现校验逻辑)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 身份证号码正则表达式详解

    公民身份号码是特征组合码,由十七位数字本体码和一 位 校验码 组成 。排列顺序从左至右依次为:六位数字地址码,八位数字出生日期码,三位数字顺序码和一位数字校验码。 地址码 : ( 身份证号码第一位到第六位 ) 表示编码对象常住户口所在 的 行政区划代码,按

    2024年02月06日
    浏览(48)
  • 8.OpenCV-识别身份证号码(Python)

    需求描述: 通过OpenCV识别身份证照片上的身份证号码(仅识别身份证号码) 实现思路: 1.将身份证号中的0,1,2,3,4,5,6,7,8,9作为模板,与身份证照片中的身份证号码区域进行模板匹配。 2.先要制作一个身份证号码模板,我这里弄了一个,基本上可以用。  3.识别出身份证照片身

    2024年02月11日
    浏览(51)
  • 根据身份证号码判断是否是未成年人

     /****      * 根据身份证号计算年龄      * @param str        * @param currDate       * @return      */     public boolean calcYear(String str, Date currDate){         DateFormat dateFormat = new SimpleDateFormat(\\\"yyyyMMdd\\\");         Long year = Long.parseLong(str.substring(0,4));         Long month = Long.parseLong(st

    2023年04月23日
    浏览(80)
  • java从身份证号码中提取出生年月日

    给一个String 类型的 身份证号码,需要从这串数字中获取出生日期、性别、年龄

    2024年02月15日
    浏览(47)
  • 身份证号码的正则表达式及验证详解(JavaScript,Regex)

    简言 在做用户实名验证时,常会用到身份证号码的正则表达式及校验方案。本文列举了两种验证方案,大家可以根据自己的项目实际情况,选择适合的方案 身份证号码说明 居民身份证号码,正确、正式的称谓应该是“公民身份号码”。根据【中华人民共和国国家标准 GB 11

    2023年04月20日
    浏览(89)
  • 身份证合法性校验规则

    身份证构成说明:   身份证号构成(从左到右): 第1-6位数是行政区域编码 第7到第14位是出生日期 第15-17位是同一天出生的顺序号(男的用奇数数,女的用偶数) 第18位是校验码,根据ISO7064:1983.MOD11-2校验码算法可以验证该身份证号是否合法身份证号。 身份证格式校验:

    2023年04月23日
    浏览(127)
  • uniapp表单uni-forms校验自定义校验规则,手机校验、身份证校验

    validateFunction 自定义校验规则 如果需要使用 validateFunction 自定义校验规则,则 不能采用 uni-forms 的 rules 属性来配置校验规则,这时候需要通过ref,在 onReady 生命周期调用组件的setRules方法绑定验证规则 无法通过props传递变量,是因为微信小程序会过滤掉对象中的方法,导致自定

    2024年02月11日
    浏览(92)
  • 前端Vue中常用rules校验规则(轮子)如电话身份证邮箱等校验

    目录 前言 一、正则是什么? 二、造轮子 三、轮子使用实例 总结 例如:随着前端的发展,很多功能都需要在前端填写时就先校验是否填写正确,则博主写了一些校验轮子供大家使用。 正则表达式(regular expression)是一个描述字符规则的对象。可以用来检查一个字符串是否含有

    2024年02月09日
    浏览(43)
  • android 校验用户名密码手机邮箱身份证邮编等

    /** 校验用户名判断:头部尾部不能使空格,不能是中文,不能使全角,不能有星号,长度6-16 其实 中文 和 全角 的 new String(charStr.getBytes(“UTF-8”),“8859_1”).getBytes().length=6 字母、数字、特殊符号new String(charStr.getBytes(“UTF-8”),“8859_1”).getBytes().length=1 */ public static boolean val

    2024年04月25日
    浏览(52)
  • android 校验用户名密码手机邮箱身份证邮编等(1)

    Pattern pattern1 = Pattern.compile(“[^u4E00-u9FA5]*”); // 不是中文 Matcher m1 = pattern1.matcher(username); if (!m1.matches()) { return false; } /** 不能有*号 */ pattern1 = Pattern.compile(“[^ ] ”); // 不是*号 m1 = pattern1.matcher(username); if (!m1.matches()) { return false; } /** 不能是纯数字 */ pattern1 = Pattern.compile(“ 1

    2024年04月25日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包