Java根據(jù)IP地址實(shí)現(xiàn)歸屬地獲取
一、使用Ip2region離線獲取
1、Ip2region簡(jiǎn)介
目前支持其他語(yǔ)言的查詢客戶端,項(xiàng)目地址:https://github.com/lionsoul2014/ip2region
Java版本的文檔:https://github.com/lionsoul2014/ip2region/blob/master/binding/java/ReadMe.md
Ip2region是一個(gè)離線IP地址定位庫(kù)和IP定位數(shù)據(jù)管理框架,10微秒級(jí)別的查詢效率,提供了眾多主流編程語(yǔ)言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn)。
2、導(dǎo)包
<dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.7.0</version> </dependency>
3、下載xdb文件
下載地址:https://github.com/lionsoul2014/ip2region/blob/master/data/ip2region.xdb
4、Java獲取IP地址歸屬地
(1)完全基于文件的查詢
基于文件的查詢性能較差,并且Searcher類是線程不安全的。并發(fā)使用,每個(gè)線程需要?jiǎng)?chuàng)建一個(gè)獨(dú)立的 searcher 對(duì)象單獨(dú)使用。
import org.lionsoul.ip2region.xdb.Searcher; import java.io.*; import java.util.concurrent.TimeUnit; public class SearcherTest { public static void main(String[] args) throws IOException { // 1、創(chuàng)建 searcher 對(duì)象,需要指定 xdb文件的位置 String dbPath = "E:\\javacodes\\ip2region.xdb"; Searcher searcher = null; try { searcher = Searcher.newWithFileOnly(dbPath); } catch (IOException e) { System.out.printf("failed to create searcher with `%s`: %s\n", dbPath, e); return; } // 2、查詢 try { String ip = "27.219.61.123"; long sTime = System.nanoTime(); String region = searcher.search(ip); long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime)); System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost); // {region: 中國(guó)|0|山東省|青島市|聯(lián)通, ioCount: 2, took: 408 μs} } catch (Exception e) { System.out.printf("failed to search", e); } // 3、關(guān)閉資源 searcher.close(); // 備注:并發(fā)使用,每個(gè)線程需要?jiǎng)?chuàng)建一個(gè)獨(dú)立的 searcher 對(duì)象單獨(dú)使用。 } }
(2)緩存 VectorIndex 索引
我們可以提前從 xdb 文件中加載出來(lái) VectorIndex 數(shù)據(jù),然后全局緩存,每次創(chuàng)建 Searcher 對(duì)象的時(shí)候使用全局的 VectorIndex 緩存可以減少一次固定的 IO 操作,從而加速查詢,減少 IO 壓力。
import org.lionsoul.ip2region.xdb.Searcher; import java.io.*; import java.util.concurrent.TimeUnit; public class SearcherTest { public static void main(String[] args) throws IOException { String dbPath = "E:\\javacodes\\SpringbootDemo\\src\\main\\resources\\ip2region.xdb"; // 1、從 dbPath 中預(yù)先加載 VectorIndex 緩存,并且把這個(gè)得到的數(shù)據(jù)作為全局變量,后續(xù)反復(fù)使用。 byte[] vIndex; try { vIndex = Searcher.loadVectorIndexFromFile(dbPath); } catch (Exception e) { System.out.printf("failed to load vector index from `%s`: %s\n", dbPath, e); return; } // 2、使用全局的 vIndex 創(chuàng)建帶 VectorIndex 緩存的查詢對(duì)象。 Searcher searcher; try { searcher = Searcher.newWithVectorIndex(dbPath, vIndex); } catch (Exception e) { System.out.printf("failed to create vectorIndex cached searcher with `%s`: %s\n", dbPath, e); return; } // 3、查詢 try { String ip = "27.219.61.123"; long sTime = System.nanoTime(); String region = searcher.search(ip); long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime)); System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost); // {region: 中國(guó)|0|山東省|青島市|聯(lián)通, ioCount: 2, took: 408 μs} } catch (Exception e) { System.out.printf("failed to search", e); } // 4、關(guān)閉資源 searcher.close(); // 備注:每個(gè)線程需要單獨(dú)創(chuàng)建一個(gè)獨(dú)立的 Searcher 對(duì)象,但是都共享全局的制度 vIndex 緩存。 } }
(3)緩存整個(gè) xdb 數(shù)據(jù)
我們也可以預(yù)先加載整個(gè) ip2region.xdb 的數(shù)據(jù)到內(nèi)存,然后基于這個(gè)數(shù)據(jù)創(chuàng)建查詢對(duì)象來(lái)實(shí)現(xiàn)完全基于文件的查詢,類似之前的 memory search。
并發(fā)使用,用整個(gè) xdb 數(shù)據(jù)緩存創(chuàng)建的查詢對(duì)象可以安全的用于并發(fā),也就是你可以把這個(gè) searcher 對(duì)象做成全局對(duì)象去跨線程訪問(wèn)。
import org.lionsoul.ip2region.xdb.Searcher; import java.io.*; import java.util.concurrent.TimeUnit; public class SearcherTest { public static void main(String[] args) { String dbPath = "E:\\javacodes\\SpringbootDemo\\src\\main\\resources\\ip2region.xdb"; // 1、從 dbPath 加載整個(gè) xdb 到內(nèi)存。 byte[] cBuff; try { cBuff = Searcher.loadContentFromFile(dbPath); } catch (Exception e) { System.out.printf("failed to load content from `%s`: %s\n", dbPath, e); return; } // 2、使用上述的 cBuff 創(chuàng)建一個(gè)完全基于內(nèi)存的查詢對(duì)象。 Searcher searcher; try { searcher = Searcher.newWithBuffer(cBuff); } catch (Exception e) { System.out.printf("failed to create content cached searcher: %s\n", e); return; } // 3、查詢 try { String ip = "27.219.61.123"; long sTime = System.nanoTime(); String region = searcher.search(ip); long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime)); System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost); // {region: 中國(guó)|0|山東省|青島市|聯(lián)通, ioCount: 0, took: 1044 μs} } catch (Exception e) { System.out.printf("failed to search", e); } // 4、關(guān)閉資源 - 該 searcher 對(duì)象可以安全用于并發(fā),等整個(gè)服務(wù)關(guān)閉的時(shí)候再關(guān)閉 searcher // searcher.close(); // 備注:并發(fā)使用,用整個(gè) xdb 數(shù)據(jù)緩存創(chuàng)建的查詢對(duì)象可以安全的用于并發(fā),也就是你可以把這個(gè) searcher 對(duì)象做成全局對(duì)象去跨線程訪問(wèn)。 } }
二、使用第三方網(wǎng)站在線查詢
在這里推薦兩個(gè)查詢網(wǎng)站,需要手動(dòng)調(diào)取API
http://ip-api.com/json/27.219.61.123?lang=zh-CN
http://whois.pconline.com.cn/ipJson.jsp?ip=27.219.61.123&json=true
以上就是Java根據(jù)IP地址實(shí)現(xiàn)歸屬地獲取的詳細(xì)內(nèi)容,更多關(guān)于Java IP地址獲取歸屬地的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java 注解@PostConstruct的原理及使用場(chǎng)景
@PostConstruct 是 Java 中用于標(biāo)記初始化方法的注解,本文將詳細(xì)講解 @PostConstruct 的原理、使用場(chǎng)景及最佳實(shí)踐,感興趣的朋友一起看看吧2025-04-04關(guān)于ReentrantLock的實(shí)現(xiàn)原理解讀
這篇文章主要介紹了關(guān)于ReentrantLock的實(shí)現(xiàn)原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06實(shí)戰(zhàn)分布式醫(yī)療掛號(hào)系統(tǒng)之設(shè)置微服務(wù)接口開(kāi)發(fā)模塊
這篇文章主要為大家介紹了實(shí)戰(zhàn)分布式醫(yī)療掛號(hào)系統(tǒng)之接口開(kāi)發(fā)醫(yī)院設(shè)置微服務(wù)模塊,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn)
這篇文章主要介紹了IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04