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

SpringBoot3集成ip2region實現(xiàn)離線IP查詢方案

 更新時間:2026年03月30日 09:35:39   作者:碼路星河  
做后端開發(fā),IP歸屬地查詢絕對是高頻剛需場景:用戶訪問日志埋點、地域權(quán)限風(fēng)控、用戶地域畫像、站點訪問統(tǒng)計,幾乎處處都能用得上,本文給大家介紹了如何基于ip2region搭建的離線IP查詢的方案,需要的朋友可以參考下

引言

做后端開發(fā),IP歸屬地查詢絕對是高頻剛需場景:用戶訪問日志埋點、地域權(quán)限風(fēng)控、用戶地域畫像、站點訪問統(tǒng)計,幾乎處處都能用得上。之前項目里用過不少第三方在線IP查詢接口,踩坑無數(shù)——高峰期接口限流、服務(wù)不穩(wěn)定宕機,還存在用戶IP隱私合規(guī)風(fēng)險,后來改用ip2region這款純離線開源查詢方案,直接解決了所有痛點。

對比下來,基于ip2region搭建的離線IP查詢方案,才更適配生產(chǎn)場景,全程本地運行、零外網(wǎng)依賴,單IP查詢速度達微秒級,常規(guī)場景精準(zhǔn)度完全夠用,而且免費開源、無調(diào)用限制。這篇文章全程只講實操、不堆砌理論,代碼復(fù)制即可運行,從環(huán)境配置到生產(chǎn)避坑一站式講透,直接照搬就能用到正式項目里。

一、項目環(huán)境與核心資源

先同步實操環(huán)境版本,避開版本兼容坑,本文全程基于ip2region 3.3.6最新穩(wěn)定版開發(fā),適配SpringBoot3生態(tài):

  • JDK 17+
  • SpringBoot 3.2.5
  • ip2region 3.3.6

核心資源說明:ip2region 官方拆分了IPv4和IPv6兩套獨立離線數(shù)據(jù)庫,需分別下載對應(yīng)xdb文件,這是實現(xiàn)雙協(xié)議查詢的關(guān)鍵,舊版單文件無法同時支持兩種IP,必須下載官方最新版雙庫文件,避免數(shù)據(jù)不匹配、查詢失敗問題。

ip2region雙庫文件下載地址(Gitee官方): 1. IPv4專用庫:https://gitee.com/lionsoul/ip2region/blob/master/data/ip2region_v4.xdb 2. IPv6專用庫:https://gitee.com/lionsoul/ip2region/blob/master/data/ip2region_v6.xdb 下載后不要重命名、不要修改后綴,嚴(yán)格保留原名區(qū)分雙庫,貼合ip2region官方加載規(guī)范。

二、Maven依賴引入

打開項目 pom.xml,直接引入ip2region核心依賴,SpringBoot3 無需額外適配包,極簡引入即可,額外推薦引入hutool工具包,簡化后續(xù)IP獲取和字符串處理,生產(chǎn)項目必備:

<!-- ip2region 離線IP歸屬地查詢核心依賴 最新3.3.6版本 -->
<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>3.3.6</version>
</dependency>
<!-- 可選:hutool工具包,簡化IP獲取和字符串處理,生產(chǎn)常用 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.25</version>
</dependency>

依賴刷新完成后,直接進入下一步數(shù)據(jù)庫文件配置,全程貼合ip2region官方API寫法,無需額外編寫復(fù)雜配置類,上手即用。

三、xdb數(shù)據(jù)庫文件放置

這一步很關(guān)鍵,ip2region雙庫文件必須規(guī)范放置,避免加載沖突,親測最優(yōu)路徑方案:

  1. 在項目 resources 目錄下,直接新建文件夾 ipdb(無需額外建子目錄)
  2. 將下載好的 ip2region_v4.xdb(IPv4庫)、ip2region_v6.xdb(IPv6庫),直接放入 resources/ipdb 目錄下
  3. 嚴(yán)格保留文件原名,不重命名、不修改后綴,防止ip2region加載路徑匹配失敗

文件放置完成后,目錄結(jié)構(gòu)參考下圖:

重點避坑:打包時如果出現(xiàn) xdb 文件丟失、損壞,需要在 pom.xml 的 build 配置中,禁止壓縮 xdb 后綴文件,后面避坑章節(jié)會詳細講,雙庫文件都需要生效該配置。

四、封裝通用IP查詢工具類

ip2region 官方針對IPv4、IPv6雙庫做了統(tǒng)一API封裝,不用手動維護兩個獨立Searcher,直接通過Config分別配置雙庫、再由Ip2Region統(tǒng)一托管即可,使用更簡潔、穩(wěn)定性更強。我采用單例模式,項目啟動時一次性加載雙庫文件,避免重復(fù)IO占用內(nèi)存,服務(wù)關(guān)閉時統(tǒng)一釋放資源,完全適配SpringBoot3資源加載規(guī)范,全局可直接調(diào)用,代碼復(fù)制即可落地:

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.service.Config;
import org.lionsoul.ip2region.service.Ip2Region;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.InputStream;
/**
 * 離線IP歸屬地查詢工具類
 * 遵循官方雙庫規(guī)范:IPv4+IPv6分開配置,統(tǒng)一托管查詢
 * 完整覆蓋所有內(nèi)網(wǎng)IP段判斷,杜絕公網(wǎng)查詢誤判
 * 單例模式,全局復(fù)用,避免重復(fù)加載數(shù)據(jù)庫
 */
@Slf4j
@Component
public class IpRegionUtil {
    /**
     * IPv4、IPv6雙庫文件路徑,對應(yīng)resources/ipdb目錄
     * 嚴(yán)格對應(yīng)ip2region官方原文件名,不修改、不重命名
     */
    private static final String IPV4_XDB_PATH = "ipdb/ip2region_v4.xdb";
    private static final String IPV6_XDB_PATH = "ipdb/ip2region_v6.xdb";
    /**
     * ip2region官方統(tǒng)一查詢對象,托管雙庫,無需手動拆分Searcher
     */
    private Ip2Region ip2Region;
    /**
     * 項目啟動初始化,加載ip2region雙庫文件
     * 采用BufferCache緩存策略,兼顧查詢速度與內(nèi)存占用
     */
    @PostConstruct
    public void init() {
        try {
            // 加載IPv4數(shù)據(jù)庫配置
            ClassPathResource v4Resource = new ClassPathResource(IPV4_XDB_PATH);
            InputStream v4Is = v4Resource.getInputStream();
            Config v4Config = Config.custom()
                    .setCachePolicy(Config.BufferCache)
                    .setSearchers(10)
                    .setXdbInputStream(v4Is)
                    .asV4();
            // 加載IPv6數(shù)據(jù)庫配置
            ClassPathResource v6Resource = new ClassPathResource(IPV6_XDB_PATH);
            InputStream v6Is = v6Resource.getInputStream();
            Config v6Config = Config.custom()
                    .setCachePolicy(Config.BufferCache)
                    .setSearchers(10)
                    .setXdbInputStream(v6Is)
                    .asV6();
            // 統(tǒng)一創(chuàng)建ip2region查詢對象
            ip2Region = Ip2Region.create(v4Config, v6Config);
            log.info("ip2region初始化成功,IPv4+IPv6雙庫加載完成");
        } catch (Exception e) {
            log.error("ip2region初始化失敗,請檢查雙庫文件路徑和完整性", e);
            throw new RuntimeException("ip2region異常,無法提供IP查詢服務(wù)");
        }
    }
    /**
     * 統(tǒng)一IP查詢?nèi)肟?,自動識別IPv4/IPv6
     * 完整過濾所有內(nèi)網(wǎng)IP,包含10段、172段、192段、本地回環(huán)
     */
    public String getIpRegion(String ip) {
        try {
            // 空IP直接返回
            if (ip == null || ip.isBlank()) {
                return "內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP";
            }
            // 判斷是否為內(nèi)網(wǎng)IP,包含IPv4全內(nèi)網(wǎng)段 + IPv6回環(huán)
            if (isPrivateIp(ip)) {
                return "內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP";
            }
            // 調(diào)用ip2region執(zhí)行公網(wǎng)IP查詢
            return ip2Region.search(ip);
        } catch (Exception e) {
            log.error("ip2region IP查詢異常,IP:{}", ip, e);
            return "查詢失敗";
        }
    }
    /**
     * 完整內(nèi)網(wǎng)IP判斷邏輯
     * IPv4內(nèi)網(wǎng)范圍:
     * 1. 127.0.0.1 本地回環(huán)
     * 2. 10.0.0.0 ~ 10.255.255.255
     * 3. 172.16.0.0 ~ 172.31.255.255
     * 4. 192.168.0.0 ~ 192.168.255.255
     * IPv6內(nèi)網(wǎng):::1 / 0:0:0:0:0:0:0:1 回環(huán)地址
     */
    private boolean isPrivateIp(String ip) {
        // IPv4內(nèi)網(wǎng)判斷
        if (ip.contains(".")) {
            // 本地回環(huán)
            if ("127.0.0.1".equals(ip)) {
                return true;
            }
            // 192.168網(wǎng)段
            if (ip.startsWith("192.168.")) {
                return true;
            }
            // 10網(wǎng)段
            if (ip.startsWith("10.")) {
                return true;
            }
            // 172.16.0.0 ~ 172.31.255.255 內(nèi)網(wǎng)段
            if (ip.startsWith("172.")) {
                String[] parts = ip.split("\\.");
                if (parts.length == 4) {
                    try {
                        int secondSegment = Integer.parseInt(parts[1]);
                        return secondSegment >= 16 && secondSegment <= 31;
                    } catch (NumberFormatException e) {
                        return false;
                    }
                }
            }
            return false;
        }
        // IPv6回環(huán)地址判斷
        return "::1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip);
    }
    /**
     * 服務(wù)關(guān)閉,釋放ip2region資源
     */
    @PreDestroy
    public void close() {
        try {
            if (ip2Region != null) {
                ip2Region.close();
                log.info("ip2region資源釋放完成");
            }
        } catch (Exception e) {
            log.error("ip2region資源釋放失敗", e);
        }
    }
}

工具類核心說明(貼合ip2region 3.3.6官方規(guī)范):

  • 嚴(yán)格遵循ip2region官方API規(guī)范,采用Config+Ip2Region統(tǒng)一托管雙庫,摒棄舊版Searcher手動維護模式,代碼更簡潔、無調(diào)用沖突,兼容性拉滿
  • 全內(nèi)網(wǎng)IP覆蓋判斷:完整包含 10 段、172.16-31 段、192.168 段、IPv4 回環(huán)及 IPv6 回環(huán)地址,徹底杜絕內(nèi)網(wǎng)IP誤查公網(wǎng)
  • 自動識別IPv4/IPv6地址,一套接口適配雙協(xié)議,業(yè)務(wù)調(diào)用無需區(qū)分IP類型,無感兼容雙網(wǎng)絡(luò)環(huán)境
  • 選用BufferCache緩存策略,平衡查詢速度與內(nèi)存占用,低配服務(wù)器可靈活切換為NoCache,適配不同部署環(huán)境
  • Spring Bean單例生命周期管理,項目啟動一次性加載雙庫,服務(wù)關(guān)閉自動釋放資源,杜絕內(nèi)存泄漏,長期運行穩(wěn)定
  • 全局異常捕獲完善,啟動失敗直接拋出明確異常,方便運維快速排查,避免后續(xù)空指針問題

五、編寫測試接口,快速驗證雙協(xié)議功能

寫一個極簡的Controller測試接口,支持兩種查詢模式:手動傳入指定IP查詢(兼容IPv4+IPv6)、自動獲取當(dāng)前請求IP查詢,適配本地調(diào)試、Nginx代理、IPv6部署場景,基于ip2region快速驗證功能是否正常:

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@Slf4j
@RestController
@RequestMapping("/ip")
@RequiredArgsConstructor
public class IpController {
    private final IpRegionUtil ipRegionUtil;
    /**
     * 手動傳入IP查詢歸屬地
     * @param ip 目標(biāo)IP
     * @return 歸屬地結(jié)果
     */
    @GetMapping("/query")
    public String queryIp(@RequestParam String ip) {
        return ipRegionUtil.getIpRegion(ip);
    }
    /**
     * 獲取當(dāng)前請求的真實IP并查詢歸屬地
     * 適配Nginx、反向代理場景,解決內(nèi)網(wǎng)IP獲取問題
     */
    @GetMapping("/current")
    public String getCurrentIpRegion(HttpServletRequest request) {
        // 優(yōu)先獲取代理轉(zhuǎn)發(fā)的真實客戶端IP
        String realIp = request.getHeader("X-Real-IP");
        if (realIp == null || realIp.isBlank()) {
            realIp = request.getRemoteAddr();
        }
        log.info("當(dāng)前請求真實客戶端IP:{}", realIp);
        return ipRegionUtil.getIpRegion(realIp);
    }
}

六、啟動項目,接口測試

1. 啟動SpringBoot項目,觀察控制臺日志,出現(xiàn) ip2region初始化成功,IPv4+IPv6雙庫加載完成 字樣,說明雙庫文件加載正常,核心工具初始化完成

2. 打開Postman或者瀏覽器,調(diào)用測試接口:

  • 公網(wǎng)IPv4測試:http://localhost:8080/api/ip/query?ip=114.114.114.114
  • 內(nèi)網(wǎng)IPv4測試(172段):http://localhost:8080/api/ip/query?ip=172.16.2.3
  • 內(nèi)網(wǎng)IPv4測試(10段):http://localhost:8080/api/ip/query?ip=10.0.0.5
  • 公網(wǎng)IPv6測試:http://localhost:8080/api/ip/query?ip=2408:8888:8888::8888
  • 當(dāng)前請求IP查詢:http://localhost:8080/api/ip/current

IPv4正常返回結(jié)果示例:中國|江蘇省|南京市|0|CN

IPv6正常返回結(jié)果示例:中國|北京|北京市|0|CN

各類內(nèi)網(wǎng)IP(10段、172段、192段、本地回環(huán))測試結(jié)果:內(nèi)網(wǎng)IP|內(nèi)網(wǎng)IP,過濾邏輯完全生效

七、常見坑與解決方案

1. 打包后找不到xdb文件,項目啟動失敗

原因:Maven打包時,默認壓縮資源文件,導(dǎo)致ip2region依賴的xdb文件損壞;或者雙庫文件路徑寫錯、少放其中一個庫文件。

解決方案:在 pom.xml 的 build 節(jié)點中,添加以下配置,禁止壓縮 xdb 后綴文件:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <exclude>*.xdb</exclude>
            </excludes>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>*.xdb</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
</build>

2. 反向代理后,獲取不到真實客戶端IP

生產(chǎn)項目基本都用Nginx代理,直接用request.getRemoteAddr()獲取的是服務(wù)器內(nèi)網(wǎng)IP,需要Nginx配置轉(zhuǎn)發(fā)真實IP,確保ip2region能查詢到真實用戶IP:

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

Java代碼中優(yōu)先讀取 X-Real-IP 請求頭,和我上面Controller代碼一致。

八、生產(chǎn)進階用法

  • 結(jié)果格式化:ip2region默認返回帶|分隔符,可封裝成VO對象,拆分國家、省份、城市、ISP字段,返回前端更友好,IPv4/IPv6查詢結(jié)果格式完全一致
  • 本地緩存:高頻查詢IP,加Caffeine或Redis緩存,減少重復(fù)調(diào)用ip2region,提升性能,IPv4和IPv6地址可共用一套緩存邏輯
  • IPv6部署適配:服務(wù)器開啟IPv6后,無需修改代碼,接口可直接接收IPv6地址,工具類自動識別并調(diào)用IPv6專用庫查詢,開箱即用
  • 定時更新雙庫:ip2region官方會單獨更新IPv4、IPv6數(shù)據(jù)庫,定時下載對應(yīng)最新xdb文件,替換對應(yīng)目錄文件,重啟服務(wù)即可,保證雙協(xié)議數(shù)據(jù)精準(zhǔn)度

九、總結(jié)

SpringBoot3集成ip2region實現(xiàn)離線IP查詢,全程不到15分鐘就能落地,純本地運行、零外網(wǎng)依賴、嚴(yán)格遵循官方雙庫規(guī)范支持IPv4+IPv6、查詢性能拉滿,完全能滿足中小項目到生產(chǎn)級別的IP查詢需求,不管是傳統(tǒng)IPv4網(wǎng)絡(luò),還是新部署的IPv6環(huán)境,都能穩(wěn)定適配。整個過程沒有復(fù)雜配置,工具類和接口代碼直接復(fù)用即可,文中的避坑方案都是實戰(zhàn)踩坑總結(jié),照著操作基本不會出現(xiàn)異常。

對比第三方在線接口,ip2region離線方案更穩(wěn)定、更安全,還沒有調(diào)用次數(shù)限制,也不用擔(dān)心隱私合規(guī)風(fēng)險,強烈建議大家把項目里的在線IP接口替換成這套方案,上手成本極低,實用性拉滿!

以上就是SpringBoot3集成ip2region實現(xiàn)離線IP查詢方案的詳細內(nèi)容,更多關(guān)于SpringBoot3 ip2region離線IP查詢的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java簡單讀取properties配置文件的方法示例

    java簡單讀取properties配置文件的方法示例

    這篇文章主要介紹了java簡單讀取properties配置文件的方法,涉及java針對properties配置的載入及文件屬性讀取相關(guān)操作技巧,需要的朋友可以參考下
    2017-09-09
  • springboot 如何取消starter的自動注入

    springboot 如何取消starter的自動注入

    這篇文章主要介紹了springboot 如何取消starter的自動注入操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Mybatis-plus設(shè)置某個字段值為null的方法總結(jié)

    Mybatis-plus設(shè)置某個字段值為null的方法總結(jié)

    mybatis-plus以下簡稱mp,目前應(yīng)該也算是主流的一款數(shù)據(jù)訪問層應(yīng)用框架,下面這篇文章主要給大家介紹了關(guān)于Mybatis-plus設(shè)置某個字段值為null的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-07-07
  • 解讀maven項目的打包方式

    解讀maven項目的打包方式

    這篇文章主要介紹了關(guān)于maven項目的打包方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 如何理解和運用ClassLoader

    如何理解和運用ClassLoader

    這篇文章主要介紹了如何理解和運用 ClassLoader,幫助大家更好的理解和使用JVM,感興趣的朋友可以了解下
    2021-01-01
  • SpringMVC自定義日期轉(zhuǎn)換器方式

    SpringMVC自定義日期轉(zhuǎn)換器方式

    這篇文章主要介紹了SpringMVC如何自定義日期轉(zhuǎn)換器問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • java調(diào)用c程序通信示例代碼

    java調(diào)用c程序通信示例代碼

    這篇文章主要介紹了java調(diào)用c程序通信示例,大家參考使用吧
    2013-12-12
  • Java反射機制,如何將一個實體類所有字段賦值為null

    Java反射機制,如何將一個實體類所有字段賦值為null

    這篇文章主要介紹了Java反射機制,如何將一個實體類所有字段賦值為null,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Mac開源開發(fā)環(huán)境搭建指南之一次配好Git、JDK、Maven、Docker

    Mac開源開發(fā)環(huán)境搭建指南之一次配好Git、JDK、Maven、Docker

    mac開發(fā)環(huán)境配置的核心在于構(gòu)建高效、隔離且可復(fù)用的工程化體系,而非單純安裝軟件,這篇文章主要介紹了Mac開源開發(fā)環(huán)境搭建指南之一次配好Git、JDK、Maven、Docker的相關(guān)資料,需要的朋友可以參考下
    2026-05-05
  • java日志LoggerFactory.getLogger的用法及說明

    java日志LoggerFactory.getLogger的用法及說明

    這篇文章主要介紹了java日志LoggerFactory.getLogger的用法及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論

林周县| 清原| 资阳市| 扎赉特旗| 石景山区| 武宣县| 孝感市| 姚安县| 平山县| 兴山县| 甘洛县| 大同市| 石台县| 泌阳县| 汶川县| 通州市| 太仓市| 博湖县| 丹凤县| 天水市| 兴海县| 神木县| 昭平县| 民县| 盐亭县| 西林县| 淮滨县| 泰安市| 开原市| 平罗县| 崇阳县| 东乌珠穆沁旗| 河池市| 永德县| 舞钢市| 恭城| 麻城市| 冷水江市| 黄冈市| 乐山市| 田东县|