身份证号码,格式校验:@IdCard(自定义注解)
目标
自定义一个用于校验 身份证号码
格式的注解@IdCard
,能够和现有的 Validation
兼容,使用方式和其他校验注解保持一致(使用 @Valid
注解接口参数)。
校验逻辑
有效格式
符合国家标准。
公民身份号码按照GB11643-1999《公民身份号码》国家标准编制,由18位数字组成:前6位为行政区划代码,第7至14位为出生日期码,第15至17位为顺序码,第18位为校验码。
严格校验
本文采用的校验方式,采用严格校验,第18位校验码
,只能为数字
或大写X
,小写x
无法通过校验。
不校验非空
身份证号码,校验的是格式;不校验是否为空(null 或 空字符串)。如果身份证号码为空,直接通过校验;
核心代码
需要定义的内容包含三个部分:
- 注解
@ZipCode
- 校验器
ZipCodeValidator
- 校验工具类
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));}}
接口测试
校验结果为 成功
校验结果为 失败
相关文章:

身份证号码,格式校验:@IdCard(自定义注解)
目标 自定义一个用于校验 身份证号码 格式的注解IdCard,能够和现有的 Validation 兼容,使用方式和其他校验注解保持一致(使用 Valid 注解接口参数)。 校验逻辑 有效格式 符合国家标准。 公民身份号码按照GB11643-…...

【Java】instanceof 关键字
instanceof 通过返回一个布尔值来指出,某个对象是否是某个特定类或者是该特定类的子类的一个实例。 如果 object 是class 的一个实例,则 instanceof 运算符返回 true,如果 object 不是指定类的一个实例,或者object 是null, 则返回…...

Android 13.0 recovery出厂时正在清理字体大小的修改
1.前言 在13.0的系统rom定制化开发中,在系统中recovery模块也是系统中比较重要的模块,比如恢复出厂设置,recovery ota升级,清理缓存等等, 在一些1080p的设备,但是density只是240这样的设备,会在恢复出厂设置的时候,显示的字体有点小,产品要求需要将正在清理的字体调大…...

京东商品数据:8月京东环境电器行业数据分析
8月份,环境电器大盘市场整体下滑。鲸参谋数据显示,8月京东平台环境电器的大盘将近570万,环比下滑约29%,同比下滑约10%;销售额为25亿,环比下滑约23%,同比下滑约8%。 *数据源于鲸参谋-行业趋势分析…...

elasticsearch(ES)分布式搜索引擎04——(数据聚合,自动补全,数据同步,ES集群)
目录 1.数据聚合1.1.聚合的种类1.2.DSL实现聚合1.2.1.Bucket聚合语法1.2.2.聚合结果排序1.2.3.限定聚合范围1.2.4.Metric聚合语法1.2.5.小结 1.3.RestAPI实现聚合1.3.1.API语法1.3.2.业务需求1.3.3.业务实现 2.自动补全2.1.拼音分词器2.2.自定义分词器2.3.自动补全查询2.4.实现…...

webdriver.Chrome()没反应
今天学习爬虫安装selenium之后刚开始webdriver.Chrome()正常 后面运行突然卡在这一步了 百度发现是版本不匹配 我们下载旧版本的chrome Download Google Chrome 95.0.4638.69 for Windows - Filehippo.com 禁用chrome的自动更新 打开文件所在位置 点击Google文件夹 右键up…...

java html转word、pdf(包含图片)
html转word maven依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.14</version> </dependency> <dependency><groupId>org.jsoup</groupId><artifactId>…...

不容易解的题10.10
5.最长回文子串 5. 最长回文子串 - 力扣(LeetCode)https://leetcode.cn/problems/longest-palindromic-substring/?envTypelist&envIdZCa7r67M给一个字符串,让我们找最长回文子串 这题不用说,回文子串那一定是连续的&#…...

淘宝天猫店铺所有商品数据接口,淘宝API接口
获取淘宝店铺所有商品数据接口的步骤如下: 获取授权:使用 OAuth 2.0 协议对应用进行授权,以便能够访问店铺的商品信息。获取店铺信息:使用淘宝 API 的 taobao.shop.get 接口,传入店铺的 user_id 参数,获取…...

Prometheus和grafana安装配置手册
1.简介 本文档为prometheus和grafana安装配置手册,prometheus和grafana的内容、和操作过程,详细介绍了服务监控配置、dashboard配置、告警配置等操作。 2.部署说明 Prometheus基于Golang编写(需要安装),编译后的软件…...

从零开始探索C语言(十一)----共用体和位域
文章目录 1. 共用体1.1 定义共用体1.2 访问共用体成员 2. 位域2.1 位域声明2.2 位域的定义和位域变量的说明2.3 位域的使用2.4 位域小结 1. 共用体 共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体&#…...

【数据结构】算法的时间复杂度
🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法时间复杂度定义 二.大O阶渐近表示法 🎏大O阶渐近表示法的定义 🎏推导大O阶方法 三.常见的时间复杂度 📌常数阶 &#x…...

Qt作业五
1、思维导图 https://www.zhixi.com/view/9e899ee0 2、作业 #include <iostream>using namespace std;class Animal { private:string name; public:Animal(){}Animal(string n):name(n){}virtual void perform()0; };class Lion:public Animal { public:void perform…...

【面试】pc寄存器题
目录 1.使用pc寄存器存储字节码指令地址有什么作用?(为什么使用pc寄存器记录当前线程的执行地址?)2.pc寄存器为什么被设定为线程私有的? 1.使用pc寄存器存储字节码指令地址有什么作用?(为什么使…...

ARM按键中断实验
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 src/do_irq.c #include "key_it.h" ex…...

C#的值类型和引用类型
不得不说c#的类型系统设计有点意思,不同的编程语言对于类型的设计各有取舍。 值类型: 当我们将一个int类型的值赋值到另一个int类型的值时,它实际上是创建了一个完全不同的副本。换句话说,如果你改变了其中某一个的值࿰…...

YOLOv7改进:极简的神经网络模型 VanillaNet---VanillaBlock助力检测,实现暴力涨点 | 华为诺亚2023
💡💡💡本文属于原创独家改进:极简模块VanillaBlock,以极简主义的设计为理念,网络中仅仅包含最简单的卷积计算,去掉了残差和注意力模块,二次创新引入到YOLOv7中取得了不俗的效果。 极简模块VanillaBlock | 亲测在多个数据集实现涨点; 收录: YOLOv7高阶自研专…...

对验证码的识别爆破
声明:该系列文章首发于公众号:Y1X1n安全,转载请注明出处!本公众号所分享内容仅用于每一个爱好者之间的技术讨论及教育目的,所有渗透及工具的使用都需获取授权,禁止用于违法途径,否则需自行承担&…...

LeetCode【15】三数之和
题目: 解析: 参考:https://zhuanlan.zhihu.com/p/111715985 代码: public static List<List<Integer>> threeSum(int[] nums) {// 先排序Arrays.sort(nums);List<List<Integer>> result new ArrayLis…...

Gossip协议是什么
Gossip协议是什么 Gossip protocol 也叫 Epidemic Protocol (流行病协议), 是基于流行病传播方式的节点或者进程之间信息交换的协议, 也被叫做流言算法, 八卦算法、疫情传播算法等等. 说到 Gossip 协议, 就不得不提著名的六度分隔理论. 简单地说, 你和任何一个陌生人之间所间…...

【java学习】this关键字(27)
文章目录 1. this是什么?2. this的作用 1. this是什么? 在 java 中,this关键字比较难理解,它的作用和其词义很接近。 ①它在方法内部使用,即这个方法所属对象的引用; ②它在构造器内部使用,表示…...

27、元组
区分: 数组:纯粹 一个[]中的数据类型都是一致的 元组:不纯粹 一个[]中可能有不同类型的数据项 意义 当赋值或访问一个已知索引的元素时,可以得到正确的类型 let miao: [string, number] [cat, 18]; miao[0] cat miao[1] 18…...

1km分辨率逐月降雨量和最高温度数据集(1901-2022)--数据处理
1km分辨率逐月降雨量和最高温度数据集(1901-2022)的下载可以参考我的另外一篇博客: 这里的温度和降雨数据集都是NC格式的,需要将其处理为tif格式,我采用的处理软件是MATLAB。 本篇博客以处理温度数据为例,…...

docker入门加实战—docker常见命令
docker入门加实战—docker常见命令 在介绍命令之前,先用一副图形象的展示一下docker的命令: 常见命令 docker的常见命令和文档地址如下表: 命令说明文档地址docker pull拉取镜像docker pulldocker push推送镜像到DockerRegistrydocker pus…...

【C/C++】使用 g++ 编译器编译 C++ 程序的完全指南
本文介绍了 g 编译器的使用方法和常见参数解释,帮助您编译和构建 C 程序。 引言 在 C 程序开发中,选择一个合适的编译器是至关重要的。g 是 GNU 编译器集合(GCC)中的 C 编译器,提供了丰富的功能和选项,帮…...

ARM中断实验
设置按键中断,按键1按下,LED亮,再按一次,灭 按键2按下,蜂鸣器响。再按一次,不响 按键3按下,风扇转,再按一次,风扇停 main.c #include "uart1.h" #include …...

Vue条件渲染
一、使用v-show条件渲染 语法格式: v-show"表达式" // true 或 false 当表达式的值为true的时候就显示,表达式值为false的时候隐藏。 下面是使用v-show实现的一个点击按钮切换显示和隐藏的小案例 : 值得注意的是,使…...

k8s中如何使用gpu、gpu资源讲解、nvidia gpu驱动安装
前言 环境:centos7.9、k8s 1.22.17、docker-ce-20.10.9 gpu资源也是服务器中常见的一种资源,gpu即显卡,一般用在人工智能、图文识别、大模型等领域,其中nvidia gpu是nvidia公司生产的nvidia类型的显卡,amd gpu则是adm…...

VRRP 虚拟路由器冗余协议的解析和配置
VRRP的解析 个人简介 原理和HSRP的差不多,少了一些状态就只有了三种状态 还有不同的就是VRRP严格按照抢占要求 一个VRRP组中具有最高优先级的设备成为Master路由器缺省优先级为100若优先级相同,具有最高接口IP地址最大的路由器成为Master路由器抢占(Pr…...

旅游网站HTML
代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>旅游网</title> </head> <body><!--采用table编辑--> <!--最晚曾table,用于整个页面那布局--><table width&q…...