由于项目对标国际,简单的正则表达式很难覆盖全面国际手机号,谷歌的libphonenumber可以很好地的很方便的很全面的实现国际收集归属地验证。
使用libphonenumber
libphonenumber是一个工具包,不增加其他第三方依赖,直接引入依赖使用即可。
- 引入libphonenumber四个jar依赖
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.12.16</version>
</dependency>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>geocoder</artifactId>
<version>2.152</version>
</dependency>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>carrier</artifactId>
<version>1.142</version>
</dependency>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>prefixmapper</artifactId>
<version>2.152</version>
</dependency>
- 使用libphonenumber工具包进行手机号处理
import com.alibaba.fastjson.JSONObject;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
import java.util.Locale;
/**
* @description:
* @author: liangbo
* @create 2021-01-20 15:38
* @Version 1.0
**/
public class PhoneUtil {
private static PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
private static PhoneNumberToCarrierMapper carrierMapper = PhoneNumberToCarrierMapper.getInstance();
private static PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
/**
* check phone
*
* @param phoneNumber eg" 18012345678"
* @param countryCode eg "86"
* @return the result "true" or "false"
*/
public static boolean checkPhoneNumber(Long phone, Integer countryCode) {
Phonenumber.PhoneNumber pn = new Phonenumber.PhoneNumber();
pn.setCountryCode(countryCode);
pn.setNationalNumber(phone);
return phoneNumberUtil.isValidNumber(pn);
}
/**
* check phone that it brings country code
*
* @param phoneNumber eg" +8618012345678"
* @return the result "true" or "false"
* @throws NumberParseException handle phone that it can't resolve
*/
public static boolean checkPhoneNumberBringCountryCode(String phoneNumber) throws NumberParseException {
Phonenumber.PhoneNumber cn = phoneNumberUtil.parse(phoneNumber, "CN");
return phoneNumberUtil.isValidNumber(cn);
}
public static JSONObject getPhoneNumberInfo(String phoneNumber) throws Exception {
Phonenumber.PhoneNumber referencePhonenumber;
try {
String language = "US";
referencePhonenumber = phoneNumberUtil.parse(phoneNumber, language);
} catch (NumberParseException e) {
throw new Exception(e.getMessage());
}
String regionCodeForNumber = phoneNumberUtil.getRegionCodeForNumber(referencePhonenumber);
if (regionCodeForNumber == null) {
throw new Exception("Missing region code by phone number " + phoneNumber);
}
boolean checkSuccess = PhoneUtil.checkPhoneNumber(referencePhonenumber.getNationalNumber(), referencePhonenumber.getCountryCode());
if (!checkSuccess) {
throw new Exception("Not an active number:" + phoneNumber);
}
String description = geocoder.getDescriptionForNumber(referencePhonenumber, Locale.CHINA);
int countryCode = referencePhonenumber.getCountryCode();
long nationalNumber = referencePhonenumber.getNationalNumber();
JSONObject resultObject = new JSONObject();
// 区域编码 Locale : HK, US, CN ...
resultObject.put("regionCode", regionCodeForNumber);
// 国号: 86, 1, 852 ... @link: https://blog.csdn.net/wzygis/article/details/45073327
resultObject.put("countryCode", countryCode);
// 去掉+号 和 国号/区号 后的实际号码
resultObject.put("nationalNumber", nationalNumber);
// 所在地区描述信息
resultObject.put("description", description);
// 去掉+号后的号码 (用于阿里云发送短信)
resultObject.put("number", String.valueOf(countryCode) + nationalNumber);
resultObject.put("fullNumber", phoneNumber);
return resultObject;
}
public static void main(String[] args) {
try {
System.out.println(getPhoneNumberInfo("+1-2843418176)").toJSONString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
使用效果
{"number":"12843418176","regionCode":"VG","nationalNumber":2843418176,"countryCode":1,"description":"英属维京群岛","fullNumber":"+1-2843418176)"}
- ps 经验证的手机号格式应该满足 “+国际区号手机号”格式,才能正确获取到手机号信息
phonenumbers 更多用法欢迎大家探讨