代码片段: IdCardConstraintValidator-IdCardConstraintValidator.java

package validator; import java.time.DateTimeException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.regex...
<pre>package validator; import java.time.DateTimeException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.apache.commons.lang3.StringUtils; /** * @Description: 身份证作为居民的唯一标识。在很多系统中需要用户输入身份证号信息,今天我们就来编写一个方法验证身份证号的合法性。 * * 首先我们来看看身份证号的编码规则: 前1-2位数字表示:所在省(直辖市、自治区)的代码; 第3-4位数字表示:所在地级市(自治州)的代码; * 第5-6位数字表示:所在区(县、自治县、县级市)的代码; 第7-14位数字表示:出生年、月、日; 第15-16位数字表示:所在地的派出所的代码; * 第17位数字表示性别:奇数表示男性,偶数表示女性; 第18位数字是校检码:也有的说是个人信息码,不是随计算机的随机产生,它是 * 用来检验身份证的正确性。校检码可以是0-9的数字,有时也用X表示。 * * 知道了规则之后,我们再来看看算法: * 第一步:将身份证号码的第1位数字与7相乘;将身份证号码的第2位数字与9相乘;将身份证号码的第3位数字与10相乘;将身份证号码的第4位数字与5相乘;将身份证号码的第5位数字与8相乘;将身份证号码的第6位数字与4相乘;将身份证号码的第7位数字与2相乘;将身份证号码的第8位数字与1相乘;将身份证号码的第9位数字与6相乘;将身份证号码的第10位数字与3相乘;将身份证号码的第11位数字与7相乘;将身份证号码的第12位数字与9相乘;将身份证号码的第13位数字与10相乘;将身份证号码的第14位数字与5相乘;将身份证号码的第15位数字与8相乘;将身份证号码的第16位数字与4相乘;将身份证号码的第17位数字与2相乘。 * 第二步:将第一步身份证号码1~17位相乘的结果求和,全部加起来。 * 第三步:用第二步计算出来的结果除以11,这样就会出现余数为0,余数为1,余数为2,余数为3,余数为4,余数为5,余数为6,余数为7,余数为8,余数为9,余数为10共11种可能性。 * 第四步:如果余数为0,那对应的最后一位身份证的号码为1;如果余数为1,那对应的最后一位身份证的号码为0;如果余数为2,那对应的最后一位身份证的号码为X;如果余数为3,那对应的最后一位身份证的号码为9;如果余数为4,那对应的最后一位身份证的号码为8;如果余数为5,那对应的最后一位身份证的号码为7;如果余数为6,那对应的最后一位身份证的号码为6;如果余数为7,那对应的最后一位身份证的号码为5;如果余数为8,那对应的最后一位身份证的号码为4;如果余数为9,那对应的最后一位身份证的号码为3;如果余数为10,那对应的最后一位身份证的号码为2。 * */ public class IdCardConstraintValidator implements ConstraintValidator<IdCard, String> { private final static String ID_CARD_REGEX = "^[1-9][0-9]{16}[0-9xX]$"; /** * <pre> * 省、直辖市代码表: * 11 : 北京 12 : 天津 13 : 河北 14 : 山西 15 : 内蒙古 * 21 : 辽宁 22 : 吉林 23 : 黑龙江 31 : 上海 32 : 江苏 * 33 : 浙江 34 : 安徽 35 : 福建 36 : 江西 37 : 山东 * 41 : 河南 42 : 湖北 43 : 湖南 44 : 广东 45 : 广西 46 : 海南 * 50 : 重庆 51 : 四川 52 : 贵州 53 : 云南 54 : 西藏 * 61 : 陕西 62 : 甘肃 63 : 青海 64 : 宁夏 65 : 新疆 * 71 : 台湾 * 81 : 香港 82 : 澳门 * 91 : 国外 * </pre> */ private final static String[] PROVINCE_CODE = { "11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36", "37", "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", "81", "82", "91" }; /** * 每位加权因子 */ private final static int[] POWER = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 }; /** * 余数对应的校验码(字符串在数组中的位置即为余数) */ private final static String[] CHECK_CODE = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" }; private boolean blankable = false; @Override public void initialize(IdCard constraintAnnotation) { if (constraintAnnotation.blankable()) { blankable = true; } } @Override public boolean isValid(String idCard, ConstraintValidatorContext context) { if (blankable && StringUtils.isBlank(idCard)) { return true; } Pattern pattern = Pattern.compile(ID_CARD_REGEX); Matcher matcher = pattern.matcher(idCard); if (matcher.matches()) { idCard = idCard.toUpperCase(); // 验证出生地 String provinceCode = idCard.substring(0, 2); if (!Arrays.asList(PROVINCE_CODE).contains(provinceCode)) { return false; } // 验证生日 String birthday = idCard.substring(6, 14); try { LocalDate now = LocalDate.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate birthdayDate = LocalDate.parse(birthday, formatter); if (birthdayDate.isAfter(now)) { return false; } } catch (DateTimeException e) { return false; } // 验证校验码 char[] c = idCard.substring(0, 17).toCharArray(); int sum17 = 0; for (int i = 0; i < c.length; i++) { int a = Integer.parseInt(String.valueOf(c[i])); sum17 += a * POWER[i]; } String checkCode = CHECK_CODE[sum17 % 11]; if (idCard.endsWith(checkCode)) { return true; } } return false; } } import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Documented; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; @Documented @Constraint(validatedBy = {IdCardConstraintValidator.class}) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @ReportAsSingleViolation @Repeatable(value = List.class) public @interface IdCard { String message() default "身份证格式错误"; /** * 是否允许校验的字段为空 * @return */ boolean blankable() default false; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) @Retention(RUNTIME) @Documented @interface List { IdCard[] value(); } } </pre>
  • 发表于 2018-07-06 15:40
  • 阅读 ( 461 )
  • 分类:代码片段

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除