国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

利用Spring Boot實現(xiàn)客戶端IP地理位置獲取

這篇具有很好參考價值的文章主要介紹了利用Spring Boot實現(xiàn)客戶端IP地理位置獲取。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端

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

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端

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

項目開源地址

home_place

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

項目概覽

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

  • common:包含一個ResultResponse類,用于統(tǒng)一處理響應(yīng)。
  • rest:負(fù)責(zé)處理客戶端請求以獲取IP地理位置的控制層。
  • service:實現(xiàn)業(yè)務(wù)邏輯,利用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文件并將其放置在服務(wù)器或本地機器上的合適位置。文件路徑在項目中配置如下:

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

響應(yīng)格式

API響應(yīng)和方法返回值的格式保持一致:

API響應(yīng):

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

方法返回值:

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

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端


性能測試

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

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

測試工具:ApiPost 7

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

時長:10秒

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端

springboot根據(jù)ip獲取地理位置,SpringBoot學(xué)習(xí),spring boot,tcp/ip,后端

致謝

該項目的功能要歸功于獅子的魂(@lionsoul)的開源貢獻,他的無私奉獻精神使我們能夠輕松地實現(xiàn)這一功能。正如俗話所說,我們都站在巨人的肩膀上。

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

后續(xù)內(nèi)容文章持續(xù)更新中…

近期發(fā)布。


關(guān)于我

????你好,我是Debug.c。微信公眾號:種顆代碼技術(shù)樹 的維護者,一個跨專業(yè)自學(xué)Java,對技術(shù)保持熱愛的bug猿,同樣也是在某二線城市打拼四年余的Java Coder。

??在掘金、CSDN、公眾號我將分享我最近學(xué)習(xí)的內(nèi)容、踩過的坑以及自己對技術(shù)的理解。

??如果您對我感興趣,請聯(lián)系我。

若有收獲,就點個贊吧,喜歡原圖請私信我。文章來源地址http://www.zghlxwxcb.cn/news/detail-828456.html

到了這里,關(guān)于利用Spring Boot實現(xiàn)客戶端IP地理位置獲取的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Spring Boot 最新版3.x 集成 OAuth 2.0實現(xiàn)認(rèn)證授權(quán)服務(wù)、第三方應(yīng)用客戶端以及資源服務(wù)

    Spring Boot 最新版3.x 集成 OAuth 2.0實現(xiàn)認(rèn)證授權(quán)服務(wù)、第三方應(yīng)用客戶端以及資源服務(wù)

    Spring Boot 3 已經(jīng)發(fā)布一段時間,網(wǎng)上關(guān)于 Spring Boot 3 的資料不是很多,本著對新技術(shù)的熱情,學(xué)習(xí)和研究了大量 Spring Boot 3 新功能和新特性,感興趣的同學(xué)可以參考 Spring 官方資料全面詳細(xì)的新功能/新改進介紹 Spring 版本升級到6.x JDK版本至少17+ … 新特性有很多,本文主要針對

    2024年02月02日
    瀏覽(97)
  • Spring Boot 整合 Redis,使用 RedisTemplate 客戶端

    Spring Boot 整合 Redis,使用 RedisTemplate 客戶端

    1.1.1 添加依賴 redis 的依賴: 1.1.2 yml 配置文件 1.1.3 Config 配置文件 1.1.4 使用示例 注入 RedisTemplate,即可操作 Redis,簡單示例如下: 1.2.1 RedisTemplate 簡介 RedisTemplate 是 Spring Data Redis 項目的一部分,旨在簡化在Java應(yīng)用程序中使用 Redis 的過程。它提供了一組簡單的方法,可以在

    2024年02月09日
    瀏覽(28)
  • 使用Spring Boot和Apache HttpClient構(gòu)建REST客戶端

    介紹: 在本文中,我們將學(xué)習(xí)如何使用Spring Boot和Apache HttpClient創(chuàng)建一個REST客戶端。我們將探討如何與遠程服務(wù)器進行通信、處理JSON響應(yīng),并為Web應(yīng)用程序配置跨源資源共享(CORS)。讓我們深入代碼吧! ClientService 類負(fù)責(zé)發(fā)起HTTP請求并處理響應(yīng)。它使用 @Service 注解表示它應(yīng)

    2024年01月16日
    瀏覽(91)
  • Netty示例教程:結(jié)合Spring Boot構(gòu)建客戶端/服務(wù)器通信

    當(dāng)涉及到在客戶端/服務(wù)器應(yīng)用程序中使用Netty進行通信時,以下是一個結(jié)合Spring Boot的示例教程,演示如何使用Netty構(gòu)建客戶端和服務(wù)器應(yīng)用程序。 簡介 本教程將指導(dǎo)您如何使用Netty結(jié)合Spring Boot構(gòu)建客戶端和服務(wù)器應(yīng)用程序。通過Netty的可靠網(wǎng)絡(luò)通信功能,您可以輕松構(gòu)建高

    2024年02月15日
    瀏覽(96)
  • 在Spring Boot微服務(wù)集成Kafka客戶端(spring-kafka)操作Kafka

    記錄 :457 場景 :在Spring Boot微服務(wù)集成Kafka客戶端spring-kafka-2.8.2操作Kafka。使用Spring封裝的KafkaTemplate操作Kafka生產(chǎn)者Producer。使用Spring封裝的@KafkaListener操作Kafka的消費者Consumer。 版本 :JDK 1.8,Spring?Boot 2.6.3,kafka_2.12-2.8.0,spring-kafka-2.8.2。 Kafka安裝 :https://blog.csdn.net/zhangbeizhen1

    2024年02月09日
    瀏覽(92)
  • 【Spring Boot Admin】客戶端服務(wù)無法注冊到監(jiān)控平臺的相關(guān)問題及解決方案

    1、客戶端服務(wù)整合了Spring Security 通過URL注冊,需在客戶端服務(wù)中添加如下配置 通過注冊中心注冊,需在客戶端服務(wù)中添加如下配置 2、客戶端服務(wù)配置了server.port.context-path參數(shù),并且客戶端服務(wù)通過注冊中心注冊 需在客戶端服務(wù)中添加如下配置 3、Spring Boot Admin 監(jiān)控平臺使

    2024年02月16日
    瀏覽(94)
  • 在Spring Boot微服務(wù)集成Kafka客戶端(kafka-clients)操作Kafka

    記錄 :459 場景 :在Spring Boot微服務(wù)集成Kafka客戶端kafka-clients-3.0.0操作Kafka。使用kafka-clients的原生KafkaProducer操作Kafka生產(chǎn)者Producer。使用kafka-clients的原生KafkaConsumer操作Kafka的消費者Consumer。 版本 :JDK 1.8,Spring?Boot 2.6.3,kafka_2.12-2.8.0,kafka-clients-3.0.0。 Kafka安裝 :https://blog.csdn.ne

    2024年02月12日
    瀏覽(91)
  • Spring Boot Starter Data Redis使用Lettuce客戶端報錯:NOAUTH Authentication required

    Spring Boot Starter Data Redis使用Lettuce客戶端報錯:NOAUTH Authentication required

    Spring Boot版本升級為:2.6.14 redis依賴: redis配置不變,還是帶password的: 項目啟動后,獲取redis連接時,報錯:NOAUTH Authentication required spring-boot-starer-data-redis支持使用Jedis和Lettuce作為redis客戶端,如果配置不指定則默認(rèn)使用Lettuce。 不管是Lettuce還是還是Jedis,核心是構(gòu)建RedisCo

    2024年01月25日
    瀏覽(27)
  • Kafka增加安全驗證安全認(rèn)證,SASL認(rèn)證,并通過spring boot-Java客戶端連接配置

    公司Kafka一直沒做安全驗證,由于是誘捕程序故需要面向外網(wǎng)連接,需要增加Kafka連接驗證,保證Kafka不被非法連接,故開始研究Kafka安全驗證 使用Kafka版本為2.4.0版本,主要參考官方文檔 官網(wǎng)對2.4版本安全驗證介紹以及使用方式地址: https://kafka.apache.org/24/documentation.html#secu

    2024年02月01日
    瀏覽(93)
  • WebSocket 實現(xiàn)長連接及通過WebSocket獲取客戶端IP

    WebSocket 是一種支持雙向通訊的網(wǎng)絡(luò)通信協(xié)議。 實現(xiàn)過程: 1 添加ServerEndpointExporter配置bean 2 實現(xiàn)過程 需求是通過WebSocket,建立長連接,并獲取當(dāng)前在線的人數(shù)。通過Websocket 不斷發(fā)送消息,建立長連接,給Session續(xù)命。我是通過MAC地址,區(qū)分不同的設(shè)備,因為我的需求中需要一

    2024年02月09日
    瀏覽(32)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包