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

SpringBoot集成IP2Region實現(xiàn)獲取IP地域信息

 更新時間:2026年03月11日 08:38:44   作者:VipSoft  
IP2Region是一個高效的離線IP地域查詢庫,這篇文章主要為大家詳細介紹了SpringBoot如何集成IP2Region實現(xiàn)獲取IP地域信息,感興趣的小伙伴可以了解下

在Java生態(tài)中,獲取IP地域信息主要有以下幾種方案:

方案優(yōu)點缺點適用場景
IP2Region離線查詢,速度快,免費數(shù)據(jù)更新需要下載新庫高并發(fā),離線環(huán)境
MaxMind GeoIP2數(shù)據(jù)準確,功能豐富商業(yè)版收費,需要更新數(shù)據(jù)庫商業(yè)應用,需要精確數(shù)據(jù)
在線API服務無需維護數(shù)據(jù)庫,使用簡單依賴網(wǎng)絡,有速率限制低頻次查詢,簡單應用

IP2Region是一個高效的離線IP地域查詢庫,具有以下特點:

  • 極致性能:微秒級的查詢速度,單核可達1000萬次/天
  • 零依賴:純Java實現(xiàn),無需第三方依賴
  • 離線查詢:不依賴網(wǎng)絡請求,數(shù)據(jù)存儲在本地
  • 簡單易用:API設計簡潔,上手快速

一、添加 Maven 依賴

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>3.3.6</version>
</dependency>

該依賴包含了 IP2Region 查詢庫,使得你能夠在 Spring Boot 項目中使用 Searcher 類進行高效的 IP 地址查詢。

二、配置數(shù)據(jù)庫文件路徑與版本

在 Spring Boot 的 application.properties 或 application.yml 中配置 IP2Region 數(shù)據(jù)庫文件的路徑和 IP 版本(IPv4 或 IPv6)。

application.yml

ip2region:
  db-path: ip2region_v4.xdb  # 可根據(jù)需要替換為 IPv6 文件路徑
  version: IPv4

ip2region_v4.xdbIP2Region 的數(shù)據(jù)庫文件,你需要下載并將其放置在 src/main/resources 目錄下,確保 Spring Boot 能夠通過 classpath 讀取。

三、創(chuàng)建 IP 查詢服務

import org.lionsoul.ip2region.xdb.Searcher;
import org.lionsoul.ip2region.xdb.Version;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;


@Service
public class IpService {

    private Searcher searcher;

    // 從配置文件中加載數(shù)據(jù)庫路徑和版本
    @Value("${ip2region.db-path}")
    private String dbPath;

    @Value("${ip2region.version}")
    private String version;

    // 服務啟動時初始化 Searcher
    @PostConstruct
    public void init() throws IOException {
        // 根據(jù)配置選擇 IP 版本
        Version ipVersion = version.equalsIgnoreCase("IPv4") ? Version.IPv4 : Version.IPv6;

        try {
            // 使用 ClassPathResource 加載類路徑中的數(shù)據(jù)庫文件
            Resource resource = new ClassPathResource(dbPath);
            if (!resource.exists()) {
                throw new IOException("Unable to find " + dbPath + " in classpath");
            }

            // 獲取文件的輸入流
            InputStream inputStream = resource.getInputStream();

            // 將 InputStream 保存到臨時文件
            Path tempFile = Files.createTempFile("ip2region", ".xdb");
            try (OutputStream out = new FileOutputStream(tempFile.toFile())) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    out.write(buffer, 0, bytesRead);
                }
            }

            // 使用臨時文件創(chuàng)建 Searcher 對象
            searcher = Searcher.newWithFileOnly(ipVersion, tempFile.toString());

        } catch (IOException e) {
            System.out.printf("failed to create searcher with `%s`: %s\n", dbPath, e);
            throw new IOException("Failed to initialize IP2Region searcher", e);
        }
    }

    // 查詢 IP 地理位置
    public String getCityInfo(String ip) {
        try {
            long sTime = System.nanoTime();
            String region = searcher.search(ip);  // 查詢 IP 地址
            long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
            System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost);
            return region;
        } catch (Exception e) {
            System.out.printf("failed to search(%s): %s\n", ip, e);
            return null;
        }
    }

    // 在 Spring Boot 中使用 @PreDestroy 優(yōu)雅地關(guān)閉 searcher
    public void close() throws IOException {
        if (searcher != null) {
            searcher.close();
        }
    }
}
  • @PostConstruct:這是 Spring 提供的生命周期注解,表示方法將在 Bean 初始化完成后執(zhí)行。我們在這里初始化 Searcher 實例,基于配置的數(shù)據(jù)庫文件路徑和 IP 版本。
  • getCityInfo:此方法用于查詢 IP 地址的地理位置信息。它會返回一個字符串,包含 IP 地址的地理位置(如國家、省份、城市等)。

四、創(chuàng)建控制器提供查詢 API

為了讓外部可以查詢 IP 地址,我們創(chuàng)建一個 REST 控制器類 IpController,通過 HTTP GET 請求提供查詢接口。

IpController.java

package com.example.ip2region.controller;

import com.example.ip2region.service.IpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IpController {

    private final IpService ipService;

    @Autowired
    public IpController(IpService ipService) {
        this.ipService = ipService;
    }

    // 查詢 IP 地址的地理信息
    @GetMapping("/get-ip-location")
    public String getIpLocation(@RequestParam String ip) {
        return ipService.getCityInfo(ip);
    }
}

解析:

@GetMapping("/get-ip-location"):此注解將 HTTP GET 請求映射到 getIpLocation 方法。通過 @RequestParam 獲取 IP 地址參數(shù),并查詢該 IP 的地理位置。

該控制器提供了一個查詢接口,可以通過 http://localhost:8080/get-ip-location?ip=1.2.3.4 查詢 IP 地址 1.2.3.4 的地理位置。

五、優(yōu)化:使用緩存來加速查詢

IP2Region 支持使用緩存來優(yōu)化查詢性能。你可以通過預加載 VectorIndex 或整個 XDB 文件的內(nèi)容,將其存儲在內(nèi)存中,從而減少文件 IO 操作,提升查詢速度。

package com.donglin.service;

import jakarta.annotation.PostConstruct;
import org.lionsoul.ip2region.xdb.Searcher;
import org.lionsoul.ip2region.xdb.Version;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;

@Service
public class IpService {

    private Searcher searcher;

    @Value("${ip2region.db-path}")
    private String dbPath;

    @Value("${ip2region.version}")
    private String version;

    @PostConstruct
    public void init() throws IOException {
        Version ipVersion = version.equalsIgnoreCase("IPv4") ? Version.IPv4 : Version.IPv6;

        try {
            // ? 1. 從 classpath 讀取 XDB 文件(無論打包與否都兼容)
            Resource resource = new ClassPathResource(dbPath);
            if (!resource.exists()) {
                throw new IOException("無法在 classpath 中找到文件:" + dbPath);
            }

            // ? 2. 先把 XDB 文件寫入臨時文件(VectorIndex 只能基于文件加載)
            Path tempFile = Files.createTempFile("ip2region", ".xdb");
            try (InputStream is = resource.getInputStream()) {
                Files.copy(is, tempFile, java.nio.file.StandardCopyOption.REPLACE_EXISTING);
            }

            // ? 3. 預加載 VectorIndex(大幅減少 I/O)
            byte[] vIndex;
            try {
                vIndex = Searcher.loadVectorIndexFromFile(tempFile.toString());
                System.out.println("VectorIndex loaded, length = " + vIndex.length);
            } catch (Exception e) {
                throw new IOException("加載 VectorIndex 失敗: " + e.getMessage(), e);
            }

            // ? 4. 創(chuàng)建使用 VectorIndex 緩存的 Searcher
            searcher = Searcher.newWithVectorIndex(ipVersion, tempFile.toString(), vIndex);
            System.out.println("IP2Region searcher initialized with vector index cache.");

        } catch (IOException e) {
            System.err.printf("failed to create searcher with `%s`: %s%n", dbPath, e);
            throw new IOException("Failed to initialize IP2Region searcher", e);
        }
    }

    // 查詢 IP 地理位置
    public String getCityInfo(String ip) {
        try {
            long start = System.nanoTime();
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - start);
            System.out.printf("{region: %s, ioCount: %d, took: %d μs}%n",
                    region, searcher.getIOCount(), cost);
            return region;
        } catch (Exception e) {
            System.err.printf("failed to search(%s): %s%n", ip, e);
            return null;
        }
    }

    public void close() throws IOException {
        if (searcher != null) {
            searcher.close();
        }
    }
}

通過將 ip2region 集成到 Spring Boot 中,我們可以非常高效地查詢 IP 地址的地理位置信息。通過預加載緩存(如 VectorIndex 或整個 XDB 文件),我們可以進一步提高查詢性能,減少 IO 壓力,尤其是在高并發(fā)場景下。

到此這篇關(guān)于SpringBoot集成IP2Region實現(xiàn)獲取IP地域信息的文章就介紹到這了,更多相關(guān)SpringBoot獲取IP信息內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • resttemplate設置params的方法

    resttemplate設置params的方法

    RestTemplate設置請求參數(shù)的方式根據(jù)請求類型(GET/POST)和參數(shù)形式(路徑參數(shù)、查詢參數(shù)、JSON請求體)有所不同,下面通過本文給大家介紹resttemplate設置params的方法,感興趣的朋友一起看看吧
    2025-04-04
  • Java Hibernate中使用HQL語句進行數(shù)據(jù)庫查詢的要點解析

    Java Hibernate中使用HQL語句進行數(shù)據(jù)庫查詢的要點解析

    HQL是Hibernate框架中提供的關(guān)系型數(shù)據(jù)庫操作腳本,當然我們也可以使用原生的SQL語句,這里我們來看一下在Java Hibernate中使用HQL語句進行數(shù)據(jù)庫查詢的要點解析:
    2016-06-06
  • Java集合系列之HashMap源碼分析

    Java集合系列之HashMap源碼分析

    這篇文章主要為大家詳細介紹了Java集合系列之HashMap源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Spring事務管理的使用細則淺析

    Spring事務管理的使用細則淺析

    事務的作用就是為了保證用戶的每一個操作都是可靠的,事務中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務開始未進行操作的狀態(tài)。事務管理是Spring框架中最為常用的功能之一,我們在使用Spring開發(fā)應用時,大部分情況下也都需要使用事務
    2023-02-02
  • springboot starter介紹與自定義starter示例詳解

    springboot starter介紹與自定義starter示例詳解

    Spring Boot 的 Starter 是一組比較方便的依賴描述符,可以通過 Maven 將其打成jar包,并在你的項目中直接引用,這篇文章主要介紹了springboot starter介紹與自定義starter示例,需要的朋友可以參考下
    2025-05-05
  • Maven倉庫無用文件和文件夾清理的方法實現(xiàn)

    Maven倉庫無用文件和文件夾清理的方法實現(xiàn)

    這篇文章主要介紹了Maven倉庫無用文件和文件夾清理的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Spring根據(jù)URL參數(shù)進行路由的方法詳解

    Spring根據(jù)URL參數(shù)進行路由的方法詳解

    這篇文章主要給大家介紹了關(guān)于Spring根據(jù)URL參數(shù)進行路由的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起來看看吧。
    2017-12-12
  • Spring?Integration概述與怎么使用詳解

    Spring?Integration概述與怎么使用詳解

    公司項目需要用到spring integration,而網(wǎng)上關(guān)于spring integration的有價值的參考資料比較少,下面這篇文章主要給大家介紹了關(guān)于Spring?Integration概述與怎么使用的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • SpringBoot集成極光推送的實現(xiàn)代碼

    SpringBoot集成極光推送的實現(xiàn)代碼

    工作中經(jīng)常會遇到服務器向App推送消息的需求,一般企業(yè)中選擇用極光推送的比較多,本文就介紹了SpringBoot集成極光推送的實現(xiàn)代碼,感興趣的可以了解一下
    2023-08-08
  • Java中的線程死鎖是什么?如何避免?

    Java中的線程死鎖是什么?如何避免?

    這篇文章主要介紹了Java中線程死鎖的相關(guān)資料,以及避免死鎖的方法,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-09-09

最新評論

申扎县| 彩票| 沅江市| 余江县| 台中市| 奉贤区| 商都县| 平度市| 全南县| 五原县| 潞西市| 连平县| 昌邑市| 社会| 江津市| 泸溪县| 阜南县| 中西区| 广州市| 鸡泽县| 揭西县| 梨树县| 双桥区| 司法| 秭归县| 青铜峡市| 宁明县| 淮南市| 会理县| 建平县| 安化县| 永善县| 吉木乃县| 海晏县| 高要市| 温泉县| 凌海市| 南平市| 绥江县| 定结县| 镇沅|