SpringBoot整合ip2region獲取客戶端IP地理位置信息
1、前言
在我們?nèi)粘EB開發(fā)工作中,經(jīng)常會(huì)有需要獲取客戶端地理位置的需求,如:發(fā)布內(nèi)容顯示城市名、系統(tǒng)統(tǒng)計(jì)監(jiān)控用戶訪問(wèn)城市等等,獲取客戶端IP的地理位置信息有助于提供個(gè)性化服務(wù)、提高用戶體驗(yàn),以及進(jìn)行數(shù)據(jù)分析和安全防護(hù)。今天博主就給大家介紹一個(gè)高效的IP地理位置庫(kù) - ip2region
目前該庫(kù)擁有16K的Srar,開源地址如下:https://github.com/lionsoul2014/ip2region
2、IP2Region簡(jiǎn)介
ip2region - 是一個(gè)離線IP地址定位庫(kù)和IP定位數(shù)據(jù)管理框架,10微秒級(jí)別的查詢效率,提供了眾多主流編程語(yǔ)言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn)。ip2region使用一個(gè)預(yù)編譯的數(shù)據(jù)庫(kù)文件,能夠以極低的內(nèi)存和CPU消耗實(shí)現(xiàn)高速查詢。與基于在線API的IP查詢相比,IP2Region的優(yōu)勢(shì)在于無(wú)需依賴外部服務(wù),響應(yīng)速度更快
主要特點(diǎn)
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 來(lái)管理你自己的 IP 定位數(shù)據(jù)。
數(shù)據(jù)去重和壓縮
xdb 格式生成程序會(huì)自動(dòng)去重和壓縮部分?jǐn)?shù)據(jù),默認(rèn)的全部 IP 數(shù)據(jù),生成的 ip2region.xdb 數(shù)據(jù)庫(kù)是11MiB,隨著數(shù)據(jù)的詳細(xì)度增加數(shù)據(jù)庫(kù)的大小也慢慢增大。
極速查詢響應(yīng)
即使是完全基于 xdb 文件的查詢,單次查詢響應(yīng)時(shí)間在十微秒級(jí)別,可通過(guò)如下兩種方式開啟內(nèi)存加速查詢:
1、vIndex 索引緩存 :使用固定的 512KiB 的內(nèi)存空間緩存 vector index 數(shù)據(jù),減少一次 IO磁盤操作,保持平均查詢效率穩(wěn)定在10-20微秒之間。
2、xdb 整個(gè)文件緩存:將整個(gè) xdb 文件全部加載到內(nèi)存,內(nèi)存占用等同于 xdb 文件大小,無(wú)磁盤 IO 操作,保持微秒級(jí)別的查詢效率。
3、項(xiàng)目初始化
? 配置依賴
創(chuàng)建一個(gè)新的 Spring Boot 項(xiàng)目,在我們的 pom.xml 文件中添加 ip2region 的依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- ip2region Starter -->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
<!-- hutool工具類 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.16</version>
</dependency>
? 配置數(shù)據(jù)文件
在ip2region項(xiàng)目中的data文件夾中下載ip2region.xdb數(shù)據(jù)庫(kù)文件,并將其放置在項(xiàng)目的resources目錄下,如圖:

? 創(chuàng)建服務(wù)類
創(chuàng)建一個(gè)服務(wù)類 IpService,用于查詢客戶端IP的地理位置。
import cn.hutool.core.io.IoUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.io.InputStream;
@Slf4j
@Service
public class IpService {
private Searcher searcher;
public IpService(){
// 加載IP數(shù)據(jù)庫(kù)
ClassPathResource resource = new ClassPathResource("ip2region/ip2region.xdb");
try {
InputStream inputStream = resource.getInputStream();
searcher = Searcher.newWithBuffer(IoUtil.readBytes(inputStream));
} catch (IOException e) {
log.error("解析ip地址失敗,無(wú)法創(chuàng)建搜索器: {}", e);
throw new RuntimeException(e);
}
}
@SneakyThrows
public String getRegion(String ip) {
String search = searcher.search(ip);
return search;
}
}
在這里,IpService類初始化時(shí)加載IP2Region的數(shù)據(jù)庫(kù)文件,并提供了一個(gè)getRegion方法,用于根據(jù)IP查詢地理位置信息
? 創(chuàng)建控制器
創(chuàng)建一個(gè)控制器 IpController,暴露一個(gè)API接口,用于獲取客戶端的IP地理位置信息
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
* @Author 李懷明
* @Date 2024/8/12 11:38 AM
* @Version 1.0
*/
@RestController
@RequestMapping("/api/ip")
public class IpController {
@Autowired
private IpService ipService;
@GetMapping("/location")
public String getLocation(@RequestParam(value = "ip", required = false) String ip, HttpServletRequest request) {
if (ip == null || ip.isEmpty()) {
ip = getIPAddress(request);
}
return ipService.getRegion(ip);
}
/**
* IP獲取處理 (可以抽離出來(lái)成為自己的工具類)
* @param request
* @return
*/
private static String getIPAddress(HttpServletRequest request) {
String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ipAddress) ? "127.0.0.1" : ipAddress;
}
}
在這個(gè)控制器中,/api/ip/location接口允許用戶傳入IP地址查詢其地理位置。如果沒有提供IP地址,則默認(rèn)使用客戶端的IP地址
? 測(cè)試與運(yùn)行
啟動(dòng)Spring Boot應(yīng)用程序后,可以通過(guò)瀏覽器或Postman訪問(wèn)以下URL來(lái)測(cè)試:
http://localhost:8080/api/ip/location?ip=124.240.3.206
這個(gè)接口將返回IP地址124.240.3.206的地理位置信息。
如果不傳入任何IP參數(shù),系統(tǒng)將自動(dòng)檢測(cè)并返回客戶端IP地址的地理位置
效果如下:

響應(yīng)內(nèi)容中包含了國(guó)家、省份、城市和運(yùn)營(yíng)商等信息
4、優(yōu)化與擴(kuò)展
封裝返回的查詢結(jié)果:博主本文主要介紹整合ip2region的簡(jiǎn)單使用,對(duì)于ip查詢結(jié)果并未進(jìn)行處理,小伙伴需要根據(jù)自己的情況合理進(jìn)行擴(kuò)展
自定義IP2Region數(shù)據(jù)庫(kù)路徑:默認(rèn)情況下,數(shù)據(jù)庫(kù)文件存儲(chǔ)在資源目錄中。你也可以將其存儲(chǔ)在其他目錄中,并通過(guò)配置文件或環(huán)境變量加載路徑。
緩存查詢結(jié)果:為了提高查詢效率,特別是在高并發(fā)環(huán)境中,可以考慮將查詢結(jié)果緩存。Spring Boot提供了多種緩存機(jī)制,如Redis或Guava Cache,可以方便地集成到IpService中。
處理IPv6地址:IP2Region主要支持IPv4地址。對(duì)于IPv6地址,可以考慮使用其他支持IPv6的地理位置查詢庫(kù),或者對(duì)IPv4和IPv6地址分別處理。
5、總結(jié)
通過(guò)整合IP2Region,Spring Boot應(yīng)用可以快速實(shí)現(xiàn)客戶端IP地理位置的查詢功能。IP2Region的高效和穩(wěn)定性使得它非常適合在各種場(chǎng)景下使用,如用戶行為分析、安全防護(hù)和個(gè)性化推薦等。
到此這篇關(guān)于SpringBoot整合ip2region獲取客戶端IP地理位置信息的文章就介紹到這了,更多相關(guān)SpringBoot獲取客戶端IP地理位置信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java解析xml文件和json轉(zhuǎn)換的方法(DOM4j解析)
相信大家都知道Java解析xml的方法有四種,每種方法都很不錯(cuò),今天通過(guò)本文給大家分享使用DOM4j進(jìn)行解析的方法,文章通過(guò)兩種方法給大家進(jìn)行解析,感興趣的朋友一起看看吧2021-08-08
關(guān)于SpringBoot攔截器攔截靜態(tài)資源的問(wèn)題
這篇文章主要介紹了關(guān)于SpringBoot攔截器攔截靜態(tài)資源的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
SpringMVC?RESTFul實(shí)戰(zhàn)案例訪問(wèn)首頁(yè)
這篇文章主要為大家介紹了SpringMVC?RESTFul實(shí)戰(zhàn)案例訪問(wèn)首頁(yè),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
微信小程序調(diào)用微信登陸獲取openid及java做為服務(wù)端示例
這篇文章主要介紹了微信小程序調(diào)用微信登陸獲取openid及java做為服務(wù)端示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01

