请求示例:
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获取