最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)根據(jù)手機(jī)號(hào)獲取歸屬地

 更新時(shí)間:2023年12月11日 17:03:53   作者:搶老婆酸奶的小肥仔  
這篇文章主要為大家詳細(xì)介紹了SpringBoot如何實(shí)現(xiàn)根據(jù)手機(jī)號(hào)獲取歸屬地,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

最近在做公司需求時(shí),甲方一會(huì)提出根據(jù)IP獲取所在地,一會(huì)有提出根據(jù)手機(jī)號(hào)獲取手機(jī)號(hào)所在地。真的是:需求時(shí)時(shí)變,累死程序猿。甲方才是爸爸。

之前已經(jīng)實(shí)現(xiàn)過(guò)根據(jù)IP獲取所在地的幾種方式,大家可以參考我之前寫(xiě)的文章下:《SpringBoot通過(guò)ip獲取歸屬地的幾種方式》。

那么今天我們來(lái)看看根據(jù)手機(jī)號(hào)有哪些方式可以獲取歸屬地呢?

廢話不多說(shuō),開(kāi)擼!

1、基于libphonenumber

libphonenumber:是谷歌提供的一款用于解析、格式化和校驗(yàn)國(guó)際手機(jī)號(hào)碼的軟件庫(kù)。它提供了三個(gè)包,分別對(duì)應(yīng)不同的功能。

libphonenumber:用于校驗(yàn)手機(jī)號(hào)的正確性,提供了:getNumberType,isNumberMatch ,getExampleNumber 等方法。

carrier:用于獲取手機(jī)號(hào)的供應(yīng)商。通過(guò)初始化PhoneNumberToCarrierMapper ,調(diào)用getNameForNumber可獲取運(yùn)營(yíng)商信息。

geocoder:用于獲取手機(jī)號(hào)的歸屬地。通過(guò)初始化PhoneNumberOfflineGeocoder ,調(diào)用getDescriptionForNumber方法可獲取手機(jī)歸屬地。

下面我們來(lái)說(shuō)說(shuō)具體實(shí)現(xiàn)。

引入包:

 <dependency>
    <groupId>com.googlecode.libphonenumber</groupId>
    <artifactId>libphonenumber</artifactId>
    <version>8.13.26</version>
</dependency>
<dependency>
    <groupId>com.googlecode.libphonenumber</groupId>
    <artifactId>carrier</artifactId>
    <version>1.210</version>
</dependency>
<dependency>
    <groupId>com.googlecode.libphonenumber</groupId>
    <artifactId>geocoder</artifactId>
    <version>2.220</version>
</dependency>

1.1 編寫(xiě)工具

引入libphonenumber所有包后,我們編寫(xiě)一個(gè)工具類(lèi),實(shí)現(xiàn)手機(jī)校驗(yàn),獲取供應(yīng)商,歸屬地等信息。

/**
 * @author: jiangjs
 * @description: 基于google的libphonenumber將手機(jī)號(hào)轉(zhuǎn)成地區(qū)及供應(yīng)商信息
 * @date: 2023/11/30 14:33
 **/
public class PhoneToRegionUtil {

    /**
     * 手機(jī)號(hào)基本工具類(lèi)
     */
    private final static PhoneNumberUtil PHONE_NUMBER_UTIL = PhoneNumberUtil.getInstance();

    /**
     * 運(yùn)營(yíng)商
     */
    private final static PhoneNumberToCarrierMapper CARRIER_MAPPER = PhoneNumberToCarrierMapper.getInstance();

    /**
     *
     */
    private final static PhoneNumberOfflineGeocoder GEO_CODER = PhoneNumberOfflineGeocoder.getInstance();

    /**
     * 驗(yàn)證當(dāng)前手機(jī)號(hào)是否有效
     * @param phone 手機(jī)號(hào)
     * @return 校驗(yàn)結(jié)果
     */
    public static boolean isValidNumber(String phone){
        return PHONE_NUMBER_UTIL.isValidNumber(getPhoneNumber(phone));
    }

    /**
     * 獲取手機(jī)號(hào)運(yùn)營(yíng)商
     * @param phone 手機(jī)號(hào)
     * @return 運(yùn)營(yíng)商
     */
    public static String getPhoneCarrier(String phone){
        return isValidNumber(phone) ?  CARRIER_MAPPER.getNameForNumber(getPhoneNumber(phone), Locale.CHINA) : "";
    }

    /**
     * 獲取手機(jī)號(hào)歸屬地
     * @param phone 手機(jī)號(hào)
     * @return 歸屬地
     */
    public static String getRegionInfoByPhone(String phone){
        return isValidNumber(phone) ? GEO_CODER.getDescriptionForNumber(getPhoneNumber(phone),Locale.CHINESE) : "";
    }

    /**
     * 生成PhoneNumber
     * @param phone 手機(jī)號(hào)
     * @return PhoneNumber
     */
    private static Phonenumber.PhoneNumber getPhoneNumber(String phone){
        Phonenumber.PhoneNumber phoneNumber = new Phonenumber.PhoneNumber();
        phoneNumber.setCountryCode(86);
        phoneNumber.setNationalNumber(Long.parseLong(phone));
        return phoneNumber;
    }

     /**
     * 獲取手機(jī)號(hào)的歸屬信息:運(yùn)營(yíng)商,歸屬地
     * @param phone 手機(jī)號(hào)
     * @return 歸屬信息
     */
    public static JSONObject getPhoneAffiliationInfo(String phone){
        JSONObject affiliation = new JSONObject();
        affiliation.put("phone",phone);
        affiliation.put("carrier",getPhoneCarrier(phone));
        affiliation.put("region",getRegionInfoByPhone(phone));
        return affiliation;
    }
}

其中,getPhoneNumber創(chuàng)建每個(gè)手機(jī)號(hào)的Phonenumber.PhoneNumber,供其他接口調(diào)用。同時(shí)在調(diào)用運(yùn)營(yíng)商等接口時(shí)先進(jìn)行手機(jī)號(hào)的校驗(yàn)。

在上面的接口中,我們會(huì)發(fā)現(xiàn)創(chuàng)建Phonenumber.PhoneNumber時(shí),會(huì)使用setCountryCode方法去設(shè)置所在國(guó)家的電話區(qū)號(hào),我們有時(shí)候復(fù)制手機(jī)號(hào)會(huì)發(fā)現(xiàn)前面是86,而86就是代表我們國(guó)家。每個(gè)國(guó)家有每個(gè)國(guó)家電話代號(hào),其他國(guó)家代號(hào),小伙伴們可以參考國(guó)際電信聯(lián)盟根據(jù) E.164 標(biāo)準(zhǔn) 分配給各國(guó)或特殊行政區(qū)的代碼。

1.2 獲取歸屬地

已經(jīng)封裝了工具類(lèi),那么接下來(lái)我們就測(cè)試一下,用手機(jī)號(hào)試試能不能獲取歸屬信息。

我們直接在Controller層中編寫(xiě)接口:

@GetMapping("/getPhoneAffiliationInfo.do/{phone}")
public JsonResult<?> getPhoneAffiliationInfo(@PathVariable("phone") String phone){
    return JsonResult.success(PhoneToRegionUtil.getPhoneAffiliationInfo(phone));
}

在瀏覽器中輸入地址,添加號(hào)碼:

通過(guò)測(cè)試,引用谷歌提供的包,可以解決我們的需求。

哈哈,可以不用加班.......

2、基于CSV文件

雖然引入谷歌的可以搞定需求了,但是作為程序員總要想想還有沒(méi)有其他方式實(shí)現(xiàn)?這不又找一種方式。哈哈

其實(shí)我們的手機(jī)號(hào)是有規(guī)律可循的:

1、前3位:前三位的數(shù)字,其實(shí)代表的是運(yùn)營(yíng)商。不同的運(yùn)營(yíng)商會(huì)提供不同的號(hào)段。比如:我的手機(jī)號(hào)是135開(kāi)頭就是移動(dòng)提供的。移動(dòng)除了提供135號(hào)段外,還有其他各種號(hào)段,如134,137等;聯(lián)通則提供了:130,131等號(hào)段;電信呢,提供了133,153等號(hào)段。

2、前7位:前7位則是可以確定手機(jī)號(hào)的歸屬地,例如:我的手機(jī)號(hào)前7位是1350154,則可以確定是廣東省廣州市。

既然我們知道了手機(jī)號(hào)的一些規(guī)律,那么如果有一份這樣的文檔,我們是不是就可以基于這份文檔進(jìn)行歸屬地的查詢(xún)呢?

還真有這樣的一份文檔,我在網(wǎng)上找到一份4年前的CSV文檔。如圖:

既然有這份文檔那我們就好實(shí)現(xiàn)了該功能。

2.1 讀取CSV文件

只所以寫(xiě)讀取CSV文件,是因?yàn)樽x取到這些信息后,想怎么查詢(xún)就由我們自己說(shuō)了算了??梢詫?shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)查詢(xún),也可以放在redis中查詢(xún)。下面我們基于redis的查詢(xún)來(lái)實(shí)現(xiàn)歸屬功能。

將CSV文件讀取到redis中。

/**
 * @author: jiangjs
 * @description: 服務(wù)啟動(dòng)后,加載數(shù)據(jù)到緩存
 * @date: 2023/12/9 15:32
 **/
@ConditionalOnProperty(havingValue = "true",value = "phoneToRegion.enabled")
@Component
public class ReadRegionToRedisStart implements CommandLineRunner {
    private final static String REGION_CSV_PATH = "classpath:/static/region/phonetmp.csv";

    private final static String PHONE_REGION_KEY = "country_phone_region_info";

    @Resource
    private ResourceLoader resourceLoader;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;


    @Override
    public void run(String... args) {
        long size = redisTemplate.opsForHash().size(PHONE_REGION_KEY);
        if (size <= 0){
            try (InputStream ism = resourceLoader.getResource(REGION_CSV_PATH).getInputStream()){
                Assert.notNull(ism,"讀取手機(jī)號(hào)信息文件為空");
                BufferedReader reader = new BufferedReader(new InputStreamReader(ism));
                String line = reader.readLine();
                while (StringUtils.isNoneBlank(line)){
                    String[] lineVal = line.split(",");
                    RegionVo regionVo = new RegionVo();
                    regionVo.setPhonePrefix(lineVal[0]).setProvince(lineVal[1]).setCity(lineVal[2]).setCarrier(lineVal[3]);
                    redisTemplate.opsForHash().put(PHONE_REGION_KEY,lineVal[0],regionVo);
                    line = reader.readLine();
                }
            }catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("獲取手機(jī)號(hào)信息報(bào)錯(cuò)");
            }
        }

    }
}

我們?cè)谙到y(tǒng)啟動(dòng)后,自動(dòng)將CSV數(shù)據(jù)加載到redis中,當(dāng)然通過(guò)@ConditionalOnProperty可以來(lái)自行決定要不要加載到內(nèi)存中。不知道@ConditionalOnProperty注解使用的小伙伴去我的主頁(yè)可以找到這篇文章來(lái)了解。

2.2 創(chuàng)建工具

數(shù)據(jù)被加載到內(nèi)存后,那么我們就可以編寫(xiě)工具類(lèi)來(lái)進(jìn)行獲取手機(jī)歸屬地。

/**
 * @author: jiangjs
 * @description: 讀取CSV文件,根據(jù)手機(jī)號(hào)前7位進(jìn)行匹配
 * @date: 2023/11/30 14:54
 **/
@Component
public class PhoneToRegionCsvUtil {

    private final static String PHONE_REGION_KEY = "country_phone_region_info";

    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    /**
     * 根據(jù)手機(jī)號(hào)獲取手機(jī)歸屬地
     * @param phone 手機(jī)號(hào)
     * @return 歸屬地信息
     */
    public RegionVo getPhoneToRegion(String phone){
        String prefix = StringUtils.substring(phone, 0, 7);
        Object region = redisTemplate.opsForHash().get(PHONE_REGION_KEY, prefix);
        return Objects.isNull(region) ? new RegionVo() : (RegionVo) region;
    }
}

2.3 獲取歸屬地

有了工具類(lèi),那我們來(lái)測(cè)試一下。

直接在Controller層中編寫(xiě)接口:

@Resource
private PhoneToRegionCsvUtil phoneToRegionCsvUtil;

@GetMapping("/getPhoneGeoInfoByCsv.do/{phone}")
public JsonResult<?> getPhoneGeoInfoByCsv(@PathVariable("phone") String phone){
    return JsonResult.success(phoneToRegionCsvUtil.getPhoneToRegion(phone));
}

瀏覽器中訪問(wèn):

至此我們也可以正常的獲取到手機(jī)號(hào)的歸屬地。

3、頁(yè)面抓取

頁(yè)面抓取這種方式,跟我之前的《SpringBoot通過(guò)ip獲取歸屬地的幾種方式》中的頁(yè)面抓取方式是一樣的,在這就不跟大家詳細(xì)介紹了。

總結(jié)

文中介紹了三種方式進(jìn)行手機(jī)號(hào)查詢(xún)歸屬地的方式。

第一種:基于谷歌提供的國(guó)際解析包,引入后不用額外引入其他的東西,只需要寫(xiě)工具類(lèi)即可,查詢(xún)速度也比較快。

第二種:基于CSV文件的,不用額外引入具體的包,但是要引入CSV文件,大小在12M多,當(dāng)然也可以將文件放在磁盤(pán)里,這樣不用擔(dān)心部署包過(guò)大。如果是基于內(nèi)存查詢(xún)的話,則需要依賴(lài)redis,增加了難度。

第三種:這個(gè)就不推薦了,畢竟依賴(lài)于第三方,如果服務(wù)掛了的話就沒(méi)法使用了。如果用戶(hù)量大的話,很可能會(huì)被第三方......,大家都懂的。

我在應(yīng)用就是使用了第一種方式。

以上就是SpringBoot實(shí)現(xiàn)根據(jù)手機(jī)號(hào)獲取歸屬地的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot手機(jī)號(hào)獲取歸屬地的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot整合MyCat實(shí)現(xiàn)讀寫(xiě)分離的方法

    SpringBoot整合MyCat實(shí)現(xiàn)讀寫(xiě)分離的方法

    這篇文章主要介紹了SpringBoot整合MyCat實(shí)現(xiàn)讀寫(xiě)分離的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 一篇文章帶你了解Java基礎(chǔ)-接口

    一篇文章帶你了解Java基礎(chǔ)-接口

    這篇文章主要介紹了java接口基礎(chǔ)知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Spring學(xué)習(xí)筆記之bean的基礎(chǔ)知識(shí)

    Spring學(xué)習(xí)筆記之bean的基礎(chǔ)知識(shí)

    ean在Spring和SpringMVC中無(wú)所不在,將這個(gè)概念內(nèi)化很重要,所以下面這篇文章主要給大家介紹了關(guān)于Spring學(xué)習(xí)筆記之bean基礎(chǔ)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳解,需要的朋友可以參考下。
    2017-12-12
  • SpringBoot集成圖片驗(yàn)證碼框架easy-captcha的詳細(xì)過(guò)程

    SpringBoot集成圖片驗(yàn)證碼框架easy-captcha的詳細(xì)過(guò)程

    本文介紹了如何將Easy-Captcha框架集成到SpringBoot項(xiàng)目中,實(shí)現(xiàn)圖片驗(yàn)證碼功能,Easy-Captcha是一款輕量級(jí)的開(kāi)源驗(yàn)證碼框架,通過(guò)簡(jiǎn)潔的API和高度可定制性,可以快速實(shí)現(xiàn)驗(yàn)證碼功能,文章詳細(xì)介紹了如何配置、生成和展示驗(yàn)證碼,并提供了Easy-Captcha的GitHub地址
    2025-03-03
  • 注冊(cè)中心配置了spring?security后客戶(hù)端啟動(dòng)報(bào)錯(cuò)

    注冊(cè)中心配置了spring?security后客戶(hù)端啟動(dòng)報(bào)錯(cuò)

    這篇文章主要為大家介紹了注冊(cè)中心配置了spring?security后客戶(hù)端啟動(dòng)報(bào)錯(cuò)問(wèn)題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 關(guān)于mybatis傳入?yún)?shù)一直為null的問(wèn)題

    關(guān)于mybatis傳入?yún)?shù)一直為null的問(wèn)題

    這篇文章主要介紹了關(guān)于mybatis傳入?yún)?shù)一直為null的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • Spring Boot中使用MongoDB的連接池配置的方法

    Spring Boot中使用MongoDB的連接池配置的方法

    本文介紹了Spring Boot中使用MongoDB的連接池配置的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • springboot實(shí)現(xiàn)配置多環(huán)境yml方式

    springboot實(shí)現(xiàn)配置多環(huán)境yml方式

    在SpringBoot項(xiàng)目中,通過(guò)創(chuàng)建不同的YAML配置文件來(lái)實(shí)現(xiàn)多環(huán)境配置是一種常見(jiàn)且有效的方法,這些配置文件包括application.yml、application-dev.yml、application-prod.yml等,分別對(duì)應(yīng)不同的開(kāi)發(fā)環(huán)境,如開(kāi)發(fā)環(huán)境、生產(chǎn)環(huán)境
    2024-11-11
  • SpringBoot中AOP的多種用途與實(shí)踐指南

    SpringBoot中AOP的多種用途與實(shí)踐指南

    Spring Boot結(jié)合AOP提供了強(qiáng)大的功能,可以用于日志記錄、性能監(jiān)控、異常處理、權(quán)限校驗(yàn)等多種場(chǎng)景,通過(guò)AOP,我們可以將橫切關(guān)注點(diǎn)從業(yè)務(wù)邏輯中分離出來(lái),從而提高代碼的可維護(hù)性和可讀性,下面就來(lái)一起了解一下
    2026-03-03
  • Springboot實(shí)現(xiàn)推薦系統(tǒng)的協(xié)同過(guò)濾算法

    Springboot實(shí)現(xiàn)推薦系統(tǒng)的協(xié)同過(guò)濾算法

    協(xié)同過(guò)濾算法是一種在推薦系統(tǒng)中廣泛使用的算法,用于預(yù)測(cè)用戶(hù)對(duì)物品(如商品、電影、音樂(lè)等)的偏好,從而實(shí)現(xiàn)個(gè)性化推薦,下面給大家介紹Springboot實(shí)現(xiàn)推薦系統(tǒng)的協(xié)同過(guò)濾算法,感興趣的朋友一起看看吧
    2025-05-05

最新評(píng)論

镇宁| 周宁县| 甘南县| 通渭县| 镇宁| 玉门市| 隆尧县| 德格县| 砚山县| 巩留县| 黔西| 汝南县| 汕头市| 射阳县| 自治县| 和政县| 任丘市| 库车县| 伊春市| 林甸县| 滨海县| 潼南县| 彰化市| 大英县| 富裕县| 昭平县| 游戏| 寿光市| 桃园市| 寿宁县| 邹城市| 务川| 黑龙江省| 精河县| 滨海县| 同心县| 宝丰县| 原平市| 浦北县| 金华市| 延川县|