身份证号码,格式校验:@IdCard(自定义注解)

目标

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

校验逻辑

有效格式

符合国家标准。

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

严格校验

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

不校验非空

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

核心代码

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

  1. 注解@ZipCode
  2. 校验器ZipCodeValidator
  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> {@Overridepublic void initialize(IdCard constraintAnnotation) {ConstraintValidator.super.initialize(constraintAnnotation);}@Overridepublic 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 {@Testvoid test() {test("110101202301024130");test("11010120230102857X");test("11010120230102857x");test("110101202301024130啊啊啊啊");}private void test(String idCard) {log.info("是否为身份证号码格式:{} = {}", idCard, IdCardUtil.isValid(idCard));}}

在这里插入图片描述

接口测试

校验结果为 成功

在这里插入图片描述
在这里插入图片描述

校验结果为 失败

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/132550.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Eziriz .NET Reactor 对c#程序加密

我目前测试过好几个c#加密软件。效果很多时候是加密后程序执行错误&#xff0c;或者字段找不到的现象 遇到这个加密软件用了一段时间都很正常&#xff0c;分享一下使用流程 破解版本自行百度。有钱的支持正版&#xff0c;我用的是 Eziriz .NET Reactor 6.8.0 第一步 安装 Ezi…

我用了多年的前端框架,强烈推荐!

大家好&#xff0c;我是鱼皮&#xff0c;今天给大家分享一个我自己用了多年、现在团队也在用的前端框架 —— Ant Design Pro。 什么是 Ant Design Pro&#xff1f; Ant Design Pro 是由蚂蚁金服开发的、基于 Ant Design 组件库的开发框架&#xff0c;专门用于构建企业级管理…

《UnityShader入门精要》学习1

读者可以在开源网站github&#xff08;https://github.com/candycat1992/Unity_Shaders_Book&#xff09;上下载本书的源代码。 第二章 渲染流水线 渲染流水线的最终目的在于生成或者说是渲染一张二维纹理&#xff0c;即我们在电脑屏幕上看到的所有效果&#xff0c;它的输入是…

java基础 IO

IO流概述&#xff1a; IO流的分类 字节流写入数据&#xff1a; package wwx;import jdk.swing.interop.SwingInterOpUtils;import java.io.*;public class Test {public static void main(String[] args) throws IOException {//指定写入文件的路径 需要抛出异常FileOutputStr…

【Java 进阶篇】HTML 语义化标签详解

HTML&#xff08;HyperText Markup Language&#xff09;是构建Web页面的标准语言。在HTML中&#xff0c;标签&#xff08;tag&#xff09;是用于定义页面结构和内容的关键元素。在构建网页时&#xff0c;了解如何正确使用HTML标签是非常重要的&#xff0c;因为它们不仅影响页面…

邮政编码,格式校验:@ZipCode(自定义注解)

目标 自定义一个用于校验邮政编码格式的注解ZipCode&#xff0c;能够和现有的 Validation 兼容&#xff0c;使用方式和其他校验注解保持一致&#xff08;使用 Valid 注解接口参数&#xff09;。 校验逻辑 有效格式 不能包含空格&#xff1b;应为6位数字&#xff1b; 不校验…

汽车一键启动点火开关按键一键启动按钮型号规格

汽车点火开关/移动管家一键启动按键/汽车改装引擎启动按钮型号&#xff1a;YD828溥款开关 一键启动按钮&#xff08;适用于配套启动主机使用或原车一键启动开关更换&#xff09; 1.适合配套专用板板安装 2.开孔器开孔安装 3.原车钥匙位安装 外观&#xff1a;黑色 按钮上有3种不…

Tomcat 线程模型性能调优

Linux I/O模型详解 I/O要解决什么问题 I/O&#xff1a;在计算机内存与外部设备之间拷贝数据的过程。 程序通过CPU向外部设备发出读指令&#xff0c;数据从外部设备拷贝至内存需要一段时间&#xff0c;这段时间CPU就没事情做了&#xff0c;程序就会两种选择&#xff1a; 让出…

以数据为中心 的AI v.s. 以模型为中心的AI

原文&#xff1a;Data-Centric AI vs. Model-Centric AI Introduction to Data-Centric AI 当你学习关于机器学习相关的课程时&#xff0c;通常是给你一个清洁好的数据,你的任务是利用这个数据集训练出一个最好的模型。所有在机器学习课程教的技巧都是为了这个目标&#xff1…

需永远在线的游戏公司,如何在线替换开源存储?

小帅是一个酷爱游戏的玩家&#xff0c;他玩一款游戏已经很久了&#xff0c;始终乐在其中。 这款游戏风靡全球&#xff0c;在中国手游出海榜单中&#xff0c;长期位居榜首。 他不知道的是&#xff0c;就在他玩游戏的过程中&#xff0c;这款游戏的出品公司&#xff0c;其实已经…

什么是存储服务器?

随着互联网的发展&#xff0c;越来越多的信息会在网络上暴露&#xff0c;所以企业就会更加重视数据&#xff0c;因此更加安全可靠的数据存储服务器受到了大多数人的信赖&#xff0c;今天就让小编带大家了解一下什么是存储服务器吧&#xff01; 存储服务器的含义。存储服务器是…

Nginx解析漏洞

常见的解析漏洞&#xff1a; IIS 5.x/6.0解析漏洞 IIS 7.0/IIS 7.5/ Nginx <0.8.3畸形解析漏洞 Nginx <8.03 空字节代码执行漏洞 Apache解析漏洞 Nginx文件解析漏洞 对于任意文件名&#xff0c;例如:cd.jpg在后面添加/x.php后&#xff0c;即可将文件作为php解析。 原理…