SpringBoot整合ip2region獲取客戶端IP地理位置信息
1、前言
在我們?nèi)粘EB開發(fā)工作中,經(jīng)常會(huì)有需要獲取客戶端地理位置的需求,如:發(fā)布內(nèi)容顯示城市名、系統(tǒng)統(tǒng)計(jì)監(jiān)控用戶訪問城市等等,獲取客戶端IP的地理位置信息有助于提供個(gè)性化服務(wù)、提高用戶體驗(yàn),以及進(jìn)行數(shù)據(jù)分析和安全防護(hù)。今天博主就給大家介紹一個(gè)高效的IP地理位置庫 - ip2region
目前該庫擁有16K的Srar,開源地址如下:https://github.com/lionsoul2014/ip2region
2、IP2Region簡(jiǎn)介
ip2region
- 是一個(gè)離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,10微秒級(jí)別的查詢效率,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn)。ip2region
使用一個(gè)預(yù)編譯的數(shù)據(jù)庫文件,能夠以極低的內(nèi)存和CPU消耗實(shí)現(xiàn)高速查詢。與基于在線API的IP查詢相比,IP2Region的優(yōu)勢(shì)在于無需依賴外部服務(wù),響應(yīng)速度更快
主要特點(diǎn)
IP 數(shù)據(jù)管理框架
xdb 支持億級(jí)別的 IP 數(shù)據(jù)段行數(shù),默認(rèn)的 region 信息都固定了格式:國家|區(qū)域|省份|城市|ISP,缺省的地域信息默認(rèn)是0。
region 信息支持完全自定義,例如:你可以在 region 中追加特定業(yè)務(wù)需求的數(shù)據(jù),例如:GPS信息/國際統(tǒng)一地域信息編碼/郵編等。也就是你完全可以使用 ip2region 來管理你自己的 IP 定位數(shù)據(jù)。
數(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ù)庫的大小也慢慢增大。
極速查詢響應(yīng)
即使是完全基于 xdb 文件的查詢,單次查詢響應(yīng)時(shí)間在十微秒級(jí)別,可通過如下兩種方式開啟內(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 文件大小,無磁盤 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ù)庫文件,并將其放置在項(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ù)庫 ClassPathResource resource = new ClassPathResource("ip2region/ip2region.xdb"); try { InputStream inputStream = resource.getInputStream(); searcher = Searcher.newWithBuffer(IoUtil.readBytes(inputStream)); } catch (IOException e) { log.error("解析ip地址失敗,無法創(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ù)庫文件,并提供了一個(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獲取處理 (可以抽離出來成為自己的工具類) * @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)用程序后,可以通過瀏覽器或Postman訪問以下URL來測(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)容中包含了國家、省份、城市和運(yùn)營(yíng)商等信息
4、優(yōu)化與擴(kuò)展
封裝返回的查詢結(jié)果:博主本文主要介紹整合ip2region的簡(jiǎn)單使用,對(duì)于ip查詢結(jié)果并未進(jìn)行處理,小伙伴需要根據(jù)自己的情況合理進(jìn)行擴(kuò)展
自定義IP2Region數(shù)據(jù)庫路徑:默認(rèn)情況下,數(shù)據(jù)庫文件存儲(chǔ)在資源目錄中。你也可以將其存儲(chǔ)在其他目錄中,并通過配置文件或環(huán)境變量加載路徑。
緩存查詢結(jié)果:為了提高查詢效率,特別是在高并發(fā)環(huán)境中,可以考慮將查詢結(jié)果緩存。Spring Boot提供了多種緩存機(jī)制,如Redis或Guava Cache,可以方便地集成到IpService中。
處理IPv6地址:IP2Region主要支持IPv4地址。對(duì)于IPv6地址,可以考慮使用其他支持IPv6的地理位置查詢庫,或者對(duì)IPv4和IPv6地址分別處理。
5、總結(jié)
通過整合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ò),今天通過本文給大家分享使用DOM4j進(jìn)行解析的方法,文章通過兩種方法給大家進(jìn)行解析,感興趣的朋友一起看看吧2021-08-08關(guān)于SpringBoot攔截器攔截靜態(tài)資源的問題
這篇文章主要介紹了關(guān)于SpringBoot攔截器攔截靜態(tài)資源的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07SpringMVC?RESTFul實(shí)戰(zhàn)案例訪問首頁
這篇文章主要為大家介紹了SpringMVC?RESTFul實(shí)戰(zhàn)案例訪問首頁,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05微信小程序調(diào)用微信登陸獲取openid及java做為服務(wù)端示例
這篇文章主要介紹了微信小程序調(diào)用微信登陸獲取openid及java做為服務(wù)端示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01