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

SpringBoot實現(xiàn)獲取客戶端IP地理位置

 更新時間:2023年11月29日 13:59:54   作者:FirstMrRight  
在當今互聯(lián)的世界中,了解客戶端的地理位置對于提供個性化服務和增強用戶體驗至關(guān)重要,使用本文為大家介紹了SpringBoot獲取客戶端IP地理位置的相關(guān)方法,需要的小伙伴可以參考下

在當今互聯(lián)的世界中,了解客戶端的地理位置對于提供個性化服務和增強用戶體驗至關(guān)重要。無論是根據(jù)地區(qū)偏好定制內(nèi)容,還是確保符合本地法規(guī),訪問客戶端IP位置都是一項寶貴的資產(chǎn)。如抖音評論區(qū)、用戶頁都會展示用戶的IP屬地信息。

在本文中,我們將探討一個Spring Boot項目,它能夠高效地獲取客戶端IP地址的地理位置,并討論其應用場景和實現(xiàn)方式。

項目開源地址

home_place

我已開源,點擊即可查看完整代碼實現(xiàn)。

項目概覽

該項目的結(jié)構(gòu)如下:

  • common:包含一個ResultResponse類,用于統(tǒng)一處理響應。
  • rest:負責處理客戶端請求以獲取IP地理位置的控制層。
  • service:實現(xiàn)業(yè)務邏輯,利用ip2region庫獲取IP位置信息。
  • util:包含主要工具類IPUtils,用于從客戶端請求中獲取IP地理位置。

項目依賴

該項目利用了開源的ip2region庫,該庫提供了離線IP地址定位和數(shù)據(jù)管理的高效API。該庫具有微秒級的查詢效率,支持多種編程語言。您可以在這里找到ip2region庫的GitHub倉庫。

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

使用方法

為了使用該項目,需下載ip2region.xdb文件并將其放置在服務器或本地機器上的合適位置。文件路徑在項目中配置如下:

private static final String DB_PATH = "/root/home_place/ip2region.xdb";

配置靈活,可使用YAML或其他配置文件進行修改。

請求處理

要獲取IP地理位置,使用javax.servlet.http.HttpServletRequest作為請求參數(shù)。調(diào)用IPUtils類的getIPRegion方法即可獲取IP位置信息:

String ipRegion = IPUtils.getIPRegion(request);

ThreadLocal的作用

ThreadLocal是Java中一個強大的工具,它提供了線程局部變量的支持。對于需要在多線程環(huán)境中保持獨立狀態(tài)的對象,ThreadLocal是一個理想的選擇。每個線程都可以通過ThreadLocal獲得自己的獨立副本,而不受其他線程的影響。

工具類

/**
 * @author Liutx
 * @since 2023-11-28 10:05
 */
public class IPUtils {

    private static final Logger log = LogManager.getLogger(IPUtils.class);

    private static final String DB_PATH = "/root/home_place/ip2region.xdb";

    private static final ThreadLocal<Searcher> searcherThreadLocal = ThreadLocal.withInitial(() -> {
        try {
            return Searcher.newWithFileOnly(DB_PATH);
        } catch (Exception e) {
            log.error("初始化 IP 歸屬地查詢失敗: {}", e.getMessage());
            return null;
        }
    });


    public static String getIPRegion(HttpServletRequest request) {
        String ip = getIPAddress(request);
        Searcher searcher = searcherThreadLocal.get();
        if (searcher == null) {
            log.error("IP 歸屬地查詢失敗,返回空");
            return null;
        }
        try {
            long startTime = System.nanoTime();
            String region = searcher.search(ip);
            long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - startTime);
            log.info("IP: {}, Region: {}, IO Count: {}, Took: {} μs", ip, region, searcher.getIOCount(), cost);
            return region;
        } catch (Exception e) {
            log.error("IP: {} 獲取 IP 歸屬地錯誤,錯誤原因: {}", ip, e.getMessage());
            return null;
        } finally {
            closeSearcher();
        }
    }


    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 ipAddress;
    }

    public static void closeSearcher() {
        try {
            Searcher searcher = searcherThreadLocal.get();
            if (Objects.nonNull(searcher)) {
                searcher.close();
                searcherThreadLocal.remove();
            }
        } catch (Exception e) {
            log.error("關(guān)閉異常", e);
        }
    }
}

Searcher在不同的線程中需要創(chuàng)建單獨的對象,因此我們使用ThreadLocal存儲,保證不同線程間的獨立性。

測試類

public static void main(String[] args) {

    String ip = "192.168.31.1";
    try {
        // 1、創(chuàng)建 searcher 對象
        String dbPath = "src/main/resources/ipdata/ip2region.xdb";
        Searcher searcher = null;
        searcher = Searcher.newWithFileOnly(dbPath);
        // 2、查詢
        long sTime = System.nanoTime();
        String region = searcher.search(ip);
        long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime));
        log.info("{region: {}, ioCount: {}, took: {} μs}", region, searcher.getIOCount(), cost);
        // 3、關(guān)閉資源
        searcher.close();
        // 備注:并發(fā)使用,每個線程需要創(chuàng)建一個獨立的 searcher 對象單獨使用。
    } catch (Exception e) {
        log.error("IP:{}獲取IP歸屬地錯誤,錯誤原因:", ip, e);
    }
}

響應格式

API響應和方法返回值的格式保持一致:

API響應:

{
  "success": true,
  "trace": "023c71f9-f483-466d-b650-a30fa097b64c",
  "code": "OK",
  "message": "獲取成功",
  "data": "中國|0|山東省|青島市|移動"
}

方法返回值:

中國|0|山東省|青島市|移動

性能測試

該項目在以下條件下進行了性能評估:

  • CPU:2核
  • RAM:2GB
  • 存儲:3MB

測試工具:ApiPost 7

并發(fā)數(shù):100

時長:10秒

總結(jié)

這個基于Spring Boot的項目,結(jié)合強大的ip2region庫,為獲取客戶端IP地理位置提供了強大的解決方案。無論是定制內(nèi)容、確保地區(qū)合規(guī)性,還是分析用戶人口統(tǒng)計信息,將IP地理位置集成到您的應用程序中都可以顯著增強其功能。隨時探索該項目,貢獻代碼,充分發(fā)揮IP地理位置在應用程序中的威力。

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

相關(guān)文章

最新評論

永济市| 白水县| 盐津县| 宝丰县| 祁连县| 大兴区| 西林县| 南宁市| 全椒县| 原平市| 天等县| 如东县| 香格里拉县| 花莲市| 梓潼县| 广河县| 沂水县| 榆中县| 万载县| 章丘市| 石渠县| 桃源县| 临西县| 夏津县| 鸡西市| 余江县| 五常市| 赞皇县| 玛曲县| 竹山县| 南漳县| 化州市| 伊川县| 武义县| 奉贤区| 龙泉市| 扶风县| 石景山区| 塘沽区| 资中县| 磴口县|