java 获取身份证号组成信息

技术概述

目前我国身份证号是由18位组成的:其中前6位是地址码,第7至14位是出生日期,第15至第17位是顺序码,它是县、区级政府所辖派出所的分配码。同时第17位也是校验性别码,奇数为男,偶数为女,第18位为校验码。

那么是如何计算第18位校验码的呢?

首先

1、将前面的身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。

2、将这17位数字和系数相乘的结果相加。

3、用加出来和除以11,看余数。

4、余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字。其分别对应的最后一位身份证的号码为1-0-X -9-8-7-6-5-4-3-2(即余数0对应1,余数1对应0,余数2对应X...)。

5、通过上面得知如果余数是3,就会在身份证的第18位数字上出现的是9。如果对应的数字是2,身份证的最后一位号码就是罗马数字X。

接下来上代码!!!

代码内容

1、ReadIdCardInformation 身份信息实体类

import lombok.Data;

@Data
public class ReadIdCardInformation {
    private String birth;
    private String age;
    private String sex;
    private String openFile;
    private String grant;
}

2、首先是 controller 文件内容 

@GetMapping("/identityInformation")
    @ApiOperation(notes = "identityInformation",value = "获取身份证信息")
    public RestResponse identityInformation(@ApiParam(name = "identityCard",value = "身份证号")@RequestParam("identityCard") String identityCard){
        ReadIdCardInformation readIdCardInformation = toolService.identityInformation(identityCard);
        return RestResponse.ok(readIdCardInformation);
    }

3、service文件内容 编写逻辑内容 调用工具类 我将身份证对应的编码存入到了数据库中,下发有sql 下载链接

public class ToolService {

@Autowired
private ReadIdCardInformationUtil readIdCardInformationUtil;
@Autowired
private ProvinceCityDistrictService provinceCityDistrictService;
/**
     * 获取身份证信息
     * @param identityCard
     * @return
     */
    public ReadIdCardInformation identityInformation(String identityCard){
        //验证身份证是否有效
        boolean flag = readIdCardInformationUtil.checkIdentityCode(identityCard);
        if(!flag){
            return null;
        }else {
            ReadIdCardInformation readIdCardInformation = new ReadIdCardInformation();
            //获取出生日期
            readIdCardInformation.setBirth(readIdCardInformationUtil.getBirth(identityCard));
            //计算年龄
            readIdCardInformation.setAge(readIdCardInformationUtil.getAge(identityCard));
            //获取性别
            readIdCardInformation.setSex(readIdCardInformationUtil.getSex(identityCard));
            //获取出生地
            String province = identityCard.substring(0,2); // 获取省
            ProvinceCityDistrict provinceCityDistrict = new ProvinceCityDistrict();
            provinceCityDistrict = provinceCityDistrictService.pcdAccurate(Integer.valueOf(province));
            if(provinceCityDistrict.getName() == null){
                readIdCardInformation.setOpenFile("无地址,请查询数据");
            }else {
                province = provinceCityDistrict.getName();
                String city = identityCard.substring(0,4);//获取市
                provinceCityDistrict = provinceCityDistrictService.pcdAccurate(Integer.valueOf(city));
                if(provinceCityDistrict.getName() == null){
                    readIdCardInformation.setOpenFile(province+"省");
                }else {
                    city = provinceCityDistrict.getName();
                    String district = identityCard.substring(0,6);//获取区
                    provinceCityDistrict = provinceCityDistrictService.pcdAccurate(Integer.valueOf(district));
                    if(provinceCityDistrict.getName() == null){
                        readIdCardInformation.setOpenFile(province+"省"+city+"市");
                    }else {
                        district = provinceCityDistrict.getName();
                        readIdCardInformation.setOpenFile(province+"省"+city+"市"+district);
                    }
                }
            }
            //获取发放身份证地点
            readIdCardInformation.setGrant(readIdCardInformationUtil.getGrant(identityCard));
            return readIdCardInformation;
        }
    }
}

4、ReadIdCardInformationUtil 工具类,里面装有关于身份证号解析

/**
 * 身份证信息读取
 */
@Slf4j
@Component
public class ReadIdCardInformationUtil {


/**
     * 身份证号校验
     */
    public boolean checkIdentityCode(String identityCode) {
        //通过正则校验身份证号格式是否正确
        if (!identityCode.matches("^[1-9]\\d{5}([1-9][1-9])\\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$")) {
            return false;
        }
        if (!ReadIdCardInformationUtil.birthVerification(identityCode)) {
            return false;
        }
        // 计算最后一位校验码 本体码各位数字乘以对应加权因子并求和 除以11得到余数是校验码  idcard是身份证
        // 本体码
        String code = identityCode.substring(0, 17);
        // 转换成数组
        int[] IDnums = new int[code.length()];
        for (int i = 0; i < code.length(); i++) {
            IDnums[i] = Integer.parseInt(String.valueOf(code.charAt(i)));
        }
        // 加权因子
        int[] x = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
        // 对应字符
        char[] checkCode = {'1', '0', 'x', '9', '8', '7', '6', '5', '4', '3', '2'};
        int sum = 0;
        for (int i = 0; i < code.length(); i++) {
            int n = code.charAt(i) - 48;
            sum = sum + n * x[i];
        }
        sum = sum % 11;
        // 验证最后一位校验码和计算出来的不匹配则不同过验证
        String identityCode18 = identityCode.substring(17, 18).toLowerCase();
        //如果为大写 X 则转换成小写 x进行比对
        if (!identityCode18.equals(String.valueOf(checkCode[sum]))){
            log.info(String.valueOf(checkCode[sum]));
            log.info("该用户身份证号码不正确,第18位校验码错误");
            return false;
        }
        return true;
    }

    /**
     * 校验出生日期 是符合出生日期格式
     *
     * @param birthDate
     * @return
     */
    public static boolean birthVerification(String birthDate) {
        Date d = new Date();
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        String currentDate = df.format(d);
        //验证出生年份不可大于当前年份
        if (Integer.parseInt(birthDate.substring(6, 10)) <= Integer.parseInt(currentDate.substring(0, 4)) &&
                Integer.parseInt(birthDate.substring(10, 12)) <= Integer.parseInt(currentDate.substring(4, 6)) &&
                Integer.parseInt(birthDate.substring(12, 14)) <= Integer.parseInt(currentDate.substring(6, 8))) {
            return true;
        }
        log.info("该用户身份证号码不正确,还没有出生");
        return false;
    }

   /**
     * 获取性别
     *
     * @param sex
     * @return
     */
    public String getSex(String sex) {
        String usex = sex.substring(14, 17);
        if (Integer.parseInt(usex) % 2 == 0) {
            return "女";
        } else {
            return "男";
        }
    }

    /**
     * 获取生日
     *
     * @param id
     * @return
     */
    public String getBirth(String id) {
        String birth = id.substring(6, 10) + "年" + id.substring(10, 12) + "月" + id.substring(12, 14) + "日";
        return birth;
    }

   /**
     * 获取出生年龄
     *
     * @param identityCardAge
     * @return
     */
    public String getAge(String identityCardAge) {
        //获取当前年份
        int year = Calendar.getInstance().get(Calendar.YEAR);
        String age = (year - Integer.parseInt(identityCardAge.substring(6, 10))) + "";
        return age;
    }

/**
     * 获取身份证顺序号
     * @param identityCardAge
     * @return
     */
    public String getGrant(String identityCardAge) {
        String grant = identityCardAge.substring(14, 17);//发放地点
        return grant;
    }

}

5、ProvinceCityDistrictService  用于获取数据库中对应区域名称 逻辑层

import cn.pl.demon.dto.mapper.ProvinceCityDistrictMapper;
import cn.pl.demon.entity.ProvinceCityDistrict;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Random;

@Service
@Slf4j
public class ProvinceCityDistrictService {
@Autowired
private ProvinceCityDistrictMapper provinceCityDistrictMapper;

   /**
     * 省市区查询
     * @param id
     * @return
     */
    public ProvinceCityDistrict pcdAccurate(Integer id){
        ProvinceCityDistrict provinceCityDistrict = provinceCityDistrictMapper.pcdAccurate(id);
        return provinceCityDistrict;
    }
}

6、ProvinceCityDistrictMapper 数据层

import cn.pl.demon.entity.ProvinceCityDistrict;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;

@Mapper
@Repository
public interface ProvinceCityDistrictMapper {

   /**
     * 省市区查询
     * @param id
     * @return
     */
    ProvinceCityDistrict pcdAccurate(Integer id);

}

7、最后就是对应的数据库了,我将数据库sql 放到了百度网盘中,下面是链接:

链接: https://pan.baidu.com/s/15Tk7Pdg-VHlbphCCOWCu3A  密码: 62ej

技术使用过程中遇到的问题以及解决过程

其实获取证件号组成信息倒不是很复杂,我主要是浪费时间在编写 验证“证件号”正则表达式上门了,头秃 ,另一个难点就是证件号最后一位校验码的算法了,如何校验已经在上面表述过了。

技术总结

总体来看这个工具类型并不是多么复杂,基本上用的都是Java的基础知识,最后还是要说基础很重要!!!

最后本人是个小萌新,请大佬们多多指教!!!!!

你可能感兴趣的:(Java,身份证号组成,证件信息获取,java,spring)