欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot整合ip2region實(shí)現(xiàn)用戶ip歸屬地獲取

 更新時(shí)間:2025年05月06日 09:27:57   作者:Anonymous395  
ip2region是一個(gè)離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn),下面我們來看看如何使用ip2region實(shí)現(xiàn)用戶ip歸屬地獲取吧

1、 Ip2region 是什么

ip2region - 是一個(gè)離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,10微秒級(jí)別的查詢效率,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn)。

2、Ip2region 特性

2.1、IP 數(shù)據(jù)管理框架

xdb 支持億級(jí)別的 IP 數(shù)據(jù)段行數(shù),默認(rèn)的 region 信息都固定了格式:國(guó)家|區(qū)域|省份|城市|ISP,缺省的地域信息默認(rèn)是0。 region 信息支持完全自定義,例如:你

可以在 region 中追加特定業(yè)務(wù)需求的數(shù)據(jù),例如:GPS信息/國(guó)際統(tǒng)一地域信息編碼/郵編等。也就是你完全可以使用 ip2region 來管理你自己的 IP 定位數(shù)據(jù)。

2.2、數(shù)據(jù)去重和壓縮

xdb 格式生成程序會(huì)自動(dòng)去重和壓縮部分?jǐn)?shù)據(jù),默認(rèn)的全部 IP 數(shù)據(jù),生成的 ip2region.xdb 數(shù)據(jù)庫是 11MiB,隨著數(shù)據(jù)的詳細(xì)度增加數(shù)據(jù)庫的大小也慢慢增大。

2.3、極速查詢響應(yīng)

即使是完全基于 xdb 文件的查詢,單次查詢響應(yīng)時(shí)間在十微秒級(jí)別,可通過如下兩種方式開啟內(nèi)存加速查詢:

  • vIndex 索引緩存 :使用固定的 512KiB 的內(nèi)存空間緩存 vector index 數(shù)據(jù),減少一次 IO 磁盤操作,保持平均查詢效率穩(wěn)定在10-20微秒之間。
  • xdb 整個(gè)文件緩存:將整個(gè) xdb 文件全部加載到內(nèi)存,內(nèi)存占用等同于 xdb 文件大小,無磁盤 IO 操作,保持微秒級(jí)別的查詢效率。

3、Ip2region的使用

步驟:

1、生成ip2region.xdb文件,做好ip2region的相關(guān)配置

2、從請(qǐng)求中獲取用戶的ip地址

3、通過ip2redion.xdb中的對(duì)應(yīng)關(guān)系找到用戶的ip對(duì)應(yīng)的地點(diǎn)(格式:`國(guó)家|區(qū)域|省份|城市|運(yùn)營(yíng)商`,缺省的地域信息默認(rèn)是0)

3.1、生成ip2region.xdb文件

下載ip2region的master分支

編譯安裝

通過 maven 來編譯可運(yùn)行 jar 程序:

# cd 到 maker/java 根目錄
mvn clean compile package

然會(huì)會(huì)在當(dāng)前目錄的 target 目錄下得到一個(gè) ip2region-maker-{version}.jar 的打包文件。

數(shù)據(jù)生成

通過 java -jar ip2region-maker-{version}.jar 來生成 ip2region.xdb 二進(jìn)制文件:

?  java git:(java_xdb_maker) ? java -jar ./target/ip2region-maker-1.0.0.jar 
ip2region xdb maker
java -jar ip2region-maker-{version}.jar [command options]
options:
 --src string    source ip text file path
 --dst string    destination binary xdb file path

例如,通過默認(rèn)的 data/ip.merge.txt 原數(shù)據(jù),在當(dāng)前目錄生成一個(gè) ip2region.xdb 二進(jìn)制文件:

在控制臺(tái)中輸入:java -jar ./target/ip2region-maker-1.0.0.jar --src=../../data/ip.merge.txt --dst=./ip2region.xdb

3.2、導(dǎo)入Ip2region的依賴

 <!-- ip2region  -->
        <dependency>
            <groupId>org.lionsoul</groupId>
            <artifactId>ip2region</artifactId>
            <version>2.6.3</version>
        </dependency>

3.3、從請(qǐng)求中獲取用戶的ip

1.全局獲取HttpServletRequest的工具類

/**
 * 全局獲取HttpServletRequest、HttpServletResponse的工具類
 */
public class HttpContextUtil {

    private HttpContextUtil() {

    }

    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
    }

    public static HttpServletResponse getHttpServletResponse() {
        return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
    }
}

2.從請(qǐng)求中獲取IP的類

public class IPUtil {

    private static final String UNKNOWN = "unknown";

    protected IPUtil() {

    }

    /**
     * 獲取 IP地址
     * 使用 Nginx等反向代理軟件, 則不能通過 request.getRemoteAddr()獲取 IP地址
     * 如果使用了多級(jí)反向代理的話,X-Forwarded-For的值并不止一個(gè),而是一串IP地址,
     * X-Forwarded-For中第一個(gè)非 unknown的有效IP字符串,則為真實(shí)IP地址
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }

}

3.通過ip從ip2region.xdb中獲取用戶歸屬地

共有三種方法:

  • 完全基于文件查詢
  • 緩存VectorIndex索引
  • 緩存整個(gè)xdb文件
public class AddressUtil {

    public static String dbPath = "src/main/resources/ip2region/ip2region.xdb";

    public static String region = "UNKOWN";

    //方法一:完全基于文件的查詢
    public static String getInfoByFie(String ip) throws IOException {
        // 1、創(chuàng)建 searcher 對(duì)象
        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 {
            //ip = "119.39.183.117";
            long sTime = System.nanoTime();
            region = searcher.searchByStr(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);
        } catch (Exception e) {
            System.out.printf("failed to search(%s): %s\n", ip, e);
        }


        return region;
        // 備注:并發(fā)使用,每個(gè)線程需要?jiǎng)?chuàng)建一個(gè)獨(dú)立的 searcher 對(duì)象單獨(dú)使用。
    }

    //方法二:緩存 VectorIndex 索引
    //我們可以提前從 xdb 文件中加載出來 VectorIndex 數(shù)據(jù),然后全局緩存,
    // 每次創(chuàng)建 Searcher 對(duì)象的時(shí)候使用全局的 VectorIndex 緩存可以減少一次固定的 IO 操作,從而加速查詢,減少 IO 壓力。
    public static String getInfoByVectorIndex(String ip) throws IOException {

        // 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 "";
        }

        // 2、查詢
        try {
            //ip = "119.39.183.117";
            long sTime = System.nanoTime();
            region = searcher.searchByStr(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);
        } catch (Exception e) {
            System.out.printf("failed to search(%s): %s\n", ip, e);
        }

        return region;
        // 備注:每個(gè)線程需要單獨(dú)創(chuàng)建一個(gè)獨(dú)立的 Searcher 對(duì)象,但是都共享全局的制度 vIndex 緩存。
    }

    //方法三:緩存整個(gè) xdb 數(shù)據(jù)
    //我們也可以預(yù)先加載整個(gè) ip2region.xdb 的數(shù)據(jù)到內(nèi)存,
    //然后基于這個(gè)數(shù)據(jù)創(chuàng)建查詢對(duì)象來實(shí)現(xiàn)完全基于文件的查詢,類似之前的 memory search。
    public static String getInfoByBuffer(String ip) throws IOException {

        // 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 "";
        }

        // 2、查詢
        try {
            //ip = "119.39.183.117";
            long sTime = System.nanoTime();
            String region = searcher.searchByStr(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);
        } catch (Exception e) {
            System.out.printf("failed to search(%s): %s\n", ip, e);
        }


        return region;
        // 備注:每個(gè)線程需要單獨(dú)創(chuàng)建一個(gè)獨(dú)立的 Searcher 對(duì)象,但是都共享全局的制度 vIndex 緩存。
    }

    public static void main(String[] args) throws IOException {
        //1、完全基于文件查詢
        String info1 = AddressUtil.getInfoByFie("203.15.235.101");
        System.out.println(info1);
        //2、緩存VectorIndex索引
        String info2 = AddressUtil.getInfoByVectorIndex("203.15.235.101");
        System.out.println(info2);
        //3、緩存整個(gè)xdb文件
        String info3 = AddressUtil.getInfoByVectorIndex("203.15.235.101");
        System.out.println(info3);
    }
}

4.測(cè)試結(jié)果

到此這篇關(guān)于Springboot整合ip2region實(shí)現(xiàn)用戶ip歸屬地獲取的文章就介紹到這了,更多相關(guān)Springboot ip2region獲取ip歸屬地內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java使用TCP套接字實(shí)現(xiàn)多人聊天功能詳解

    Java使用TCP套接字實(shí)現(xiàn)多人聊天功能詳解

    這篇文章主要介紹了Java使用TCP套接字實(shí)現(xiàn)多人聊天功能,結(jié)合實(shí)例形式詳細(xì)分析了java使用socket通信實(shí)現(xiàn)tcp協(xié)議下的聊天功能客戶端與服務(wù)器端相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-10-10
  • Java類的訪問權(quán)限關(guān)鍵字用法說明

    Java類的訪問權(quán)限關(guān)鍵字用法說明

    這篇文章主要介紹了Java類的訪問權(quán)限關(guān)鍵字用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java字節(jié)流和字符流及IO流的總結(jié)

    Java字節(jié)流和字符流及IO流的總結(jié)

    本文主要將Java中的IO流進(jìn)行了梳理,通過將其分成字節(jié)流和字符流,以及輸入流和輸出流分別統(tǒng)計(jì),來建立一個(gè)對(duì) Java中IO流全局的概念,通過一些實(shí)例來演示了如何通過不同類型的流來組合實(shí)現(xiàn)強(qiáng)大靈活的輸入和輸出,最后介紹了同時(shí)支持輸入和輸出的 RandomAccessFile。
    2021-04-04
  • Jmeter參數(shù)化獲取序列數(shù)據(jù)實(shí)現(xiàn)過程

    Jmeter參數(shù)化獲取序列數(shù)據(jù)實(shí)現(xiàn)過程

    這篇文章主要介紹了Jmeter參數(shù)化獲取序列數(shù)據(jù)實(shí)現(xiàn)過程,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 基于String實(shí)現(xiàn)同步鎖的方法步驟

    基于String實(shí)現(xiàn)同步鎖的方法步驟

    這篇文章主要給大家介紹了關(guān)于基于String實(shí)現(xiàn)同步鎖的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用String具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 詳解Java實(shí)現(xiàn)LRU緩存

    詳解Java實(shí)現(xiàn)LRU緩存

    這篇文章主要介紹了詳解Java實(shí)現(xiàn)LRU緩存,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • Spring的Aware接口實(shí)現(xiàn)及執(zhí)行順序詳解

    Spring的Aware接口實(shí)現(xiàn)及執(zhí)行順序詳解

    這篇文章主要為大家介紹了Spring的Aware接口實(shí)現(xiàn)及執(zhí)行順序詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Java實(shí)現(xiàn)兩人五子棋游戲(五) 判斷是否有一方勝出

    Java實(shí)現(xiàn)兩人五子棋游戲(五) 判斷是否有一方勝出

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)兩人五子棋游戲,判斷是否有一方勝出,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇)

    詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇)

    這篇文章主要介紹了詳解Java 包掃描實(shí)現(xiàn)和應(yīng)用(Jar篇),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 獲取Spring的上下文環(huán)境ApplicationContext的最簡(jiǎn)單方式

    獲取Spring的上下文環(huán)境ApplicationContext的最簡(jiǎn)單方式

    這篇文章主要介紹了獲取Spring的上下文環(huán)境ApplicationContext的最簡(jiǎn)單方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評(píng)論