SpringBoot实现手机号归属地查询功能,轻松获取手机号码信息

程序员必备网站icon-default.png?t=N7T8https://tmxkj.top/#/

请求示例:

1

 1.Util工具类

import org.springframework.beans.factory.annotation.Value;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;

/**
 * 获取手机号信息方法
 */
public class PhoneNumberGeo {

    private static final String[] PHONE_NUMBER_TYPE = {null, "移动", "联通", "电信", "电信虚拟运营商", "联通虚拟运营商", "移动虚拟运营商"};
    private static final int INDEX_SEGMENT_LENGTH = 9;
    private static final int DATA_FILE_LENGTH_HINT = 3747505;
    @Value("${customInfo.phone.path}")
    private static final String PHONE_DAT_FILE_PATH = "static/phone.dat";

    private static byte[] dataByteArray;
    private static int indexAreaOffset;
    private static int phoneRecordCount;

    private final ByteBuffer byteBuffer;

    private static synchronized void initData() {
        if (dataByteArray == null) {
            ByteArrayOutputStream byteData = new ByteArrayOutputStream(DATA_FILE_LENGTH_HINT);
            byte[] buffer = new byte[1024];

            int readBytesLength;
            try (InputStream inputStream = PhoneNumberGeo.class.getClassLoader().getResourceAsStream(PHONE_DAT_FILE_PATH)) {
                if (inputStream != null) {
                    while ((readBytesLength = inputStream.read(buffer)) != -1) {
                        byteData.write(buffer, 0, readBytesLength);
                    }
                }
            } catch (Exception e) {
                System.err.println("Can't find phone.dat in classpath: " + PHONE_DAT_FILE_PATH);
                e.fillInStackTrace();
                throw new RuntimeException(e);
            }

            dataByteArray = byteData.toByteArray();

            ByteBuffer byteBuffer = ByteBuffer.wrap(dataByteArray);
            byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
            int dataVersion = byteBuffer.getInt();
            indexAreaOffset = byteBuffer.getInt();
            phoneRecordCount = (dataByteArray.length - indexAreaOffset) / INDEX_SEGMENT_LENGTH;

            // print data version
            // System.out.println(dataVersion);
            // print record count
            // System.out.println(phoneRecordCount);
        }
    }

    public PhoneNumberGeo() {
        initData();

        byteBuffer = ByteBuffer.wrap(dataByteArray);
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
    }

    public PhoneInfo lookup(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.length() > 11 || phoneNumber.length() < 7) {
            return null;
        }
        int phoneNumberPrefix;
        try {
            phoneNumberPrefix = Integer.parseInt(phoneNumber.substring(0, 7));
        } catch (Exception e) {
            return null;
        }
        int left = 0;
        int right = phoneRecordCount;
        while (left <= right) {
            int middle = (left + right) >> 1;
            int currentOffset = indexAreaOffset + middle * INDEX_SEGMENT_LENGTH;
            if (currentOffset >= dataByteArray.length) {
                return null;
            }

            byteBuffer.position(currentOffset);
            int currentPrefix = byteBuffer.getInt();
            if (currentPrefix > phoneNumberPrefix) {
                right = middle - 1;
            } else if (currentPrefix < phoneNumberPrefix) {
                left = middle + 1;
            } else {
                int infoBeginOffset = byteBuffer.getInt();
                int phoneType = byteBuffer.get();

                int infoLength = -1;
                for (int i = infoBeginOffset; i < indexAreaOffset; ++i) {
                    if (dataByteArray[i] == 0) {
                        infoLength = i - infoBeginOffset;
                        break;
                    }
                }

                String infoString = new String(dataByteArray, infoBeginOffset, infoLength, StandardCharsets.UTF_8);
                String[] infoSegments = infoString.split("\\|");

                PhoneInfo phoneInfo = new PhoneInfo();
                phoneInfo.setPhoneNumber(phoneNumber);
                phoneInfo.setProvince(infoSegments[0]);
                phoneInfo.setCity(infoSegments[1]);
                phoneInfo.setZipCode(infoSegments[2]);
                phoneInfo.setAreaCode(infoSegments[3]);
                phoneInfo.setPhoneType(PHONE_NUMBER_TYPE[phoneType]);
                return phoneInfo;
            }
        }
        return null;
    }

}
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class VerifyUitl {
    /**
     * 判断是否是手机号
     * @param phoneNumber
     * @return
     */
    public static boolean isPhoneNumber(String phoneNumber) {
        String regex = "^1[3-9]\\d{9}$";
        return Pattern.matches(regex, phoneNumber);
    }

    /**
     * 校验QQ邮箱号
     * @param email 邮箱地址
     * @return 是否有效
     */
    public static boolean isQQEmail(String email) {
        // 定义QQ邮箱的正则表达式
        String regex = "^[1-9][0-9]{4,10}@qq\\.com$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(email);
        return matcher.matches();
    }
}

 

 2.Dto实体类

import lombok.Data;

@Data
public class PhoneInfo {
    private String phoneNumber;
    private String province;
    private String city;
    private String zipCode;
    private String areaCode;
    private String phoneType;
}

3.Controller控制层

@RestController
public class GeoIPController {

    /**
     * 获取手机号信息
     */
  //  @RateLimit
    @GetMapping("/phone-info")
    public Result getPhoneInfo(@RequestParam("mobile") String mobile) {
        Result result = new Result();
        PhoneNumberGeo phoneNumberGeo = new PhoneNumberGeo();
        if (mobile==null || mobile.isEmpty()) {
            result.setCode(404);
            result.setMsg("手机号码不能为空!");
        }else if (isPhoneNumber(mobile)){
            PhoneInfo phoneInfo = phoneNumberGeo.lookup(mobile);
            if (phoneInfo != null) {
                result.setMsg("获取手机号信息成功");
                result.setData(phoneInfo);
            }else {
                result.setCode(404);
                result.setMsg("获取手机信息错误");
            }
        }else {
            result.setCode(400);
            result.setMsg("手机号格式错误!");
        }
        return result;
    }
}

4.yml 文件

# 自定义信息
customInfo:
  phone:
    path: "static/phone.dat"

备注:phone.dat文件获取关注公众号天梦星科技综合服务回复phone.dat获取

 

  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值