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

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

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

1、 Ip2region 是什么

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

2、Ip2region 特性

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

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

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

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

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

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

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

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

3、Ip2region的使用

步驟:

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

2、從請求中獲取用戶的ip地址

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

3.1、生成ip2region.xdb文件

下載ip2region的master分支

編譯安裝

通過 maven 來編譯可運行 jar 程序:

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

然會會在當前目錄的 target 目錄下得到一個 ip2region-maker-{version}.jar 的打包文件。

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

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

?  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

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

在控制臺中輸入: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、從請求中獲取用戶的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.從請求中獲取IP的類

public class IPUtil {

    private static final String UNKNOWN = "unknown";

    protected IPUtil() {

    }

    /**
     * 獲取 IP地址
     * 使用 Nginx等反向代理軟件, 則不能通過 request.getRemoteAddr()獲取 IP地址
     * 如果使用了多級反向代理的話,X-Forwarded-For的值并不止一個,而是一串IP地址,
     * X-Forwarded-For中第一個非 unknown的有效IP字符串,則為真實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索引
  • 緩存整個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 對象
        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ā)使用,每個線程需要創(chuàng)建一個獨立的 searcher 對象單獨使用。
    }

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

        // 1、從 dbPath 中預(yù)先加載 VectorIndex 緩存,并且把這個得到的數(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 緩存的查詢對象。
        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;
        // 備注:每個線程需要單獨創(chuàng)建一個獨立的 Searcher 對象,但是都共享全局的制度 vIndex 緩存。
    }

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

        // 1、從 dbPath 中預(yù)先加載 VectorIndex 緩存,并且把這個得到的數(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 緩存的查詢對象。
        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;
        // 備注:每個線程需要單獨創(chuàng)建一個獨立的 Searcher 對象,但是都共享全局的制度 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、緩存整個xdb文件
        String info3 = AddressUtil.getInfoByVectorIndex("203.15.235.101");
        System.out.println(info3);
    }
}

4.測試結(jié)果

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

相關(guān)文章

  • 深入分析JAVA Vector和Stack的具體用法

    深入分析JAVA Vector和Stack的具體用法

    這篇文章主要介紹了深入分析JAVA Vector和Stack的具體用法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java生成PDF文檔兩個超實用的庫( iText和Apache PDFBox)

    Java生成PDF文檔兩個超實用的庫( iText和Apache PDFBox)

    這篇文章主要介紹了Java生成PDF文檔兩個超實用的庫,分別是用 iText庫以及用Apache PDFBox庫生成PDF,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-02-02
  • Java基礎(chǔ)之反射原理與用法詳解

    Java基礎(chǔ)之反射原理與用法詳解

    這篇文章主要介紹了Java基礎(chǔ)之反射原理與用法,結(jié)合實例形式詳細分析了java反射的相關(guān)概念、原理、使用方法與操作注意事項,需要的朋友可以參考下
    2020-02-02
  • Java基于UDP協(xié)議實現(xiàn)簡單的聊天室程序

    Java基于UDP協(xié)議實現(xiàn)簡單的聊天室程序

    這篇文章主要為大家詳細介紹了Java基于UDP協(xié)議實現(xiàn)簡單的聊天室程序的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • 解決druid監(jiān)控頁面SQL不顯示的問題

    解決druid監(jiān)控頁面SQL不顯示的問題

    這篇文章主要介紹了解決druid監(jiān)控頁面SQL不顯示的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java單例模式的應(yīng)用示例

    Java單例模式的應(yīng)用示例

    這篇文章主要介紹了Java單例模式的應(yīng)用示例,需要的朋友可以參考下
    2014-02-02
  • 利用Spring?boot+LogBack+MDC實現(xiàn)鏈路追蹤

    利用Spring?boot+LogBack+MDC實現(xiàn)鏈路追蹤

    這篇文章主要介紹了利用Spring?boot+LogBack+MDC實現(xiàn)鏈路追蹤,MDC?可以看成是一個與當前線程綁定的哈希表,可以往其中添加鍵值對,下文詳細介紹需要的小伙伴可以參考一下
    2022-04-04
  • java通過AES生成公鑰加密數(shù)據(jù)ECC加密公鑰

    java通過AES生成公鑰加密數(shù)據(jù)ECC加密公鑰

    這篇文章主要為大家介紹了java通過AES生成公鑰加密數(shù)據(jù)ECC加密公鑰實現(xiàn)案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽流程分析

    SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽流程分析

    這篇文章主要介紹了SpringBoot+JWT實現(xiàn)注冊、登錄、狀態(tài)續(xù)簽【登錄保持】,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • Java基礎(chǔ)篇之serialVersionUID用法及注意事項詳解

    Java基礎(chǔ)篇之serialVersionUID用法及注意事項詳解

    這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)篇之serialVersionUID用法及注意事項的相關(guān)資料,SerialVersionUID屬性是用于序列化/反序列化可序列化類的對象的標識符,我們可以用它來記住可序列化類的版本,以驗證加載的類和序列化對象是否兼容,需要的朋友可以參考下
    2024-02-02

最新評論

莱芜市| 城口县| 隆尧县| 长乐市| 萝北县| 江口县| 永登县| 峨边| 凤冈县| 顺义区| 张家港市| 浪卡子县| 兴安盟| 黄冈市| 修武县| 都江堰市| 四子王旗| 荥经县| 丰镇市| 方正县| 枞阳县| 台前县| 唐河县| 和林格尔县| 广平县| 治多县| 滦南县| 遂溪县| 德化县| 开平市| 望都县| 论坛| 遂溪县| 阜平县| 彭州市| 育儿| 南康市| 长海县| 始兴县| 德清县| 信丰县|