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

JAVA使用Ip2region獲取IP定位信息的操作方法

 更新時(shí)間:2022年05月27日 14:56:00   作者:喵喵撲  
這篇文章主要介紹了JAVA使用Ip2region獲取IP定位信息,ip2region?-?是國內(nèi)開發(fā)者開發(fā)的離線IP地址定位庫,針對(duì)國內(nèi)IP效果較好,國外的部分IP只能顯示國家,對(duì)java獲取IP定位信息操作過程感興趣的朋友一起看看吧

ip2region - 準(zhǔn)確率99.9%的離線IP地址定位庫,0.0x毫秒級(jí)查詢

ip2region - 是國內(nèi)開發(fā)者開發(fā)的離線IP地址定位庫,針對(duì)國內(nèi)IP效果較好,國外的部分IP只能顯示國家。

項(xiàng)目gitee地址:

https://gitee.com/lionsoul/ip2region.git

先安裝依賴

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

下載離線IP定位庫

離線數(shù)據(jù)庫在項(xiàng)目的data文件夾下,名稱為ip2region.db,其他2個(gè)文件是用于生成離線庫的,可不用下載。

https://gitee.com/lionsoul/ip2region/blob/master/data/ip2region.db

下載到離線數(shù)據(jù)庫后,我們需要讀取這個(gè)數(shù)據(jù)庫,我們可以放在項(xiàng)目的resources目錄,但是我不建議這樣做,這樣打包的jar會(huì)變得很大,部署時(shí)麻煩。

我們指定一個(gè)絕對(duì)路徑,這個(gè)部署的時(shí)候也不用每次上傳,這個(gè)數(shù)據(jù)庫一般不會(huì)修改,如果數(shù)據(jù)庫更新了,單獨(dú)上傳即可。

因?yàn)槲覀冺?xiàng)目使用阿里云oss,服務(wù)器也在阿里云,所以我就把數(shù)據(jù)庫存到oss中,阿里云內(nèi)網(wǎng)讀取還是很快的,這樣免得我修改地址,更新數(shù)據(jù)庫我也只需要在本地上傳到oss即可。

下面我們定義類封裝ip2region

  • 記錄映射實(shí)體 IpInfo.java

該類用于接受解析后的數(shù)據(jù),我們也可以使用map來接收,我這里就使用模型來組裝數(shù)據(jù)。

類使用 lombok ,如果不喜歡的自行修改為普通類。

import lombok.Data;
/**
 * 域名信息.
 *
 * @author https://www.cnblogs.com/lixingwu
 * @date 2022-05-24 15:07:47
 */
@Data
public class IpInfo {
    /*** 國家 */
    private String country;
    /*** 地區(qū) */
    private String region;
    /*** 省 */
    private String province;
    /*** 市 */
    private String city;
    /*** 運(yùn)營商 */
    private String isp;
}

ip解析工具類 Ip2regionAnalysis.java

該類主要用于加載數(shù)據(jù)庫和解析IP信息,然后把查詢的結(jié)果組裝為IpInfo的;

這個(gè)類我使用了使用單例模式(雙重校驗(yàn)鎖DCL)進(jìn)行編寫,在構(gòu)造函數(shù)里加載IP數(shù)據(jù)庫,這樣數(shù)據(jù)庫就只會(huì)加載一遍。

類中還用到了工具包hutool,需要自行引入,具體操作自行百度。

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.yunding.vote.domain.IpInfo;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbMakerConfigException;
import org.lionsoul.ip2region.DbSearcher;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashSet;
import java.util.Optional;
/**
 * 使用單例模式(雙重校驗(yàn)鎖DCL)
 *
 * @author https://www.cnblogs.com/lixingwu
 * @date 2022-05-24 10:45:42
 */
@Slf4j
public class Ip2regionAnalysis {
    private volatile static Ip2regionAnalysis analysis;
    /**
     * TODO 這個(gè)數(shù)據(jù)庫地址,改成自己的,不要用這地址啊,這個(gè)需要登錄才能下載
     * ip數(shù)據(jù)庫地址
     */
    public static final String IP_REGION_DB_URL = "https://gitee.com/lionsoul/ip2region/raw/master/data/ip2region.db";
    /**
     * ip數(shù)據(jù)庫字節(jié)
     */
    private final byte[] dbBinStr;
    /**
     * 初始化,下載ip數(shù)據(jù)庫文件轉(zhuǎn)為為文件輸出流
     */
    private Ip2regionAnalysis() {
        // 下載IP數(shù)據(jù)庫文件
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HttpUtil.download(IP_REGION_DB_URL, outputStream, false, new StreamProgress() {
            @Override
            public void start() {
                log.info("下載IP數(shù)據(jù)庫文件...");
            }
            @Override
            public void progress(long progressSize) {
            }
            @Override
            public void finish() {
                double fileSize = NumberUtil.div(outputStream.size(), (1024 * 1024), 2);
                log.info("IP數(shù)據(jù)庫文件下載成功,數(shù)據(jù)庫文件大小[{}MB]", fileSize);
            }
        });
        dbBinStr = outputStream.toByteArray();
        IoUtil.close(outputStream);
    }
    /**
     * 獲取IP解析單例
     *
     * @return Ip2regionAnalysis
     */
    public static Ip2regionAnalysis getInstance() {
        if (analysis == null) {
            synchronized (Ip2regionAnalysis.class) {
                if (analysis == null) {
                    analysis = new Ip2regionAnalysis();
                }
            }
        }
        return analysis;
    }
    /**
     * <p>方法名稱:解析Ip信息.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 11:26:59</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param ip IP地址
     * @return 國家|區(qū)域|省份|城市|ISP
     */
    public Optional<String> getIpInfo(String ip) {
        if (IpAddressUtil.validIp(ip)) {
            try {
                DbConfig config = new DbConfig();
                DbSearcher searcher = new DbSearcher(config, dbBinStr);
                // 搜索數(shù)據(jù)
                DataBlock search = searcher.memorySearch(ip);
                // 數(shù)據(jù)格式:國家|區(qū)域|省份|城市|ISP
                return Optional.of(search.getRegion());
            } catch (DbMakerConfigException | IOException e) {
                e.printStackTrace();
                log.error("Ip解析失?。簕}", e.toString());
            }
        }
        return Optional.empty();
    }
    /**
     * <p>方法名稱:解析Ip信息.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 11:26:59</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param ips IP地址集合
     * @return Dict({ ip : info })
     */
    public Dict getIpInfo(HashSet<String> ips) {
        try {
            DbConfig config = new DbConfig();
            DbSearcher searcher = new DbSearcher(config, dbBinStr);
            DataBlock search;
            Dict dataset = Dict.create();
            for (String ip : ips) {
                if (IpAddressUtil.validIp(ip)) {
                    search = searcher.memorySearch(ip);
                    dataset.set(ip, search.getRegion());
                }
            }
            return dataset;
        } catch (DbMakerConfigException | IOException e) {
            e.printStackTrace();
            log.error("Ip解析失敗:{}", e.toString());
        }
        return Dict.create();
    }
    /**
     * <p>方法名稱:數(shù)字ip獲取信息.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 13:15:23</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param ip 數(shù)字IP
     * @return 國家|區(qū)域|省份|城市|ISP
     */
    public Optional<String> getIpInfo(long ip) {
        String longIpv4 = NetUtil.longToIpv4(ip);
        return getIpInfo(longIpv4);
    }
    /**
     * <p>方法名稱:獲取請(qǐng)求對(duì)象的IP信息.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 11:50:59</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param request 請(qǐng)求對(duì)象
     * @return 國家|區(qū)域|省份|城市|ISP
     */
    public Optional<String> getIpInfo(HttpServletRequest request) {
        String ip = IpAddressUtil.getIpAddr(request);
        return getIpInfo(ip);
    }
    /**
     * <p>方法名稱:獲取IP信息的字典.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 11:52:58</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param ip IP地址
     * @return the dict
     */
    public IpInfo getIpInfoBean(String ip) {
        Optional<String> ipInfo = getIpInfo(ip);
        IpInfo info = new IpInfo();
        if (ipInfo.isPresent()) {
            //國家|區(qū)域|省份|城市|ISP
            String[] split = StrUtil.split(ipInfo.get(), "|");
            info.setCountry(split[0]);
            info.setRegion(split[1]);
            info.setProvince(split[2]);
            info.setCity(split[3]);
            info.setIsp(split[4]);
        }
        return info;
    }
    /**
     * <p>方法名稱:數(shù)字ip獲取信息字典.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 13:15:23</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param ip 數(shù)字IP
     * @return 國家|區(qū)域|省份|城市|ISP
     */
    public IpInfo getIpInfoBean(long ip) {
        String longIpv4 = NetUtil.longToIpv4(ip);
        return getIpInfoBean(longIpv4);
    }
    /**
     * <p>方法名稱:獲取IP信息的字典.</p>
     * <p>詳細(xì)描述:.</p>
     * <p>創(chuàng)建時(shí)間:2022-05-24 11:52:58</p>
     * <p>創(chuàng)建作者:lixingwu</p>
     * <p>修改記錄:</p>
     *
     * @param request 請(qǐng)求對(duì)象
     * @return the dict
     */
    public IpInfo getIpInfoBean(HttpServletRequest request) {
        String ip = IpAddressUtil.getIpAddr(request);
        return getIpInfoBean(ip);
    }
    /**
     * 測(cè)試
     */
    public static void main(String[] args) {
        log.info("121.8.215.106 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("121.8.215.106"));
        log.info("183.247.152.98 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("183.247.152.98"));
        log.info("14.29.139.251 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("14.29.139.251"));
        log.info("183.247.152.98 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("183.247.152.98"));
        log.info("27.105.130.93 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("27.105.130.93"));
        log.info("124.205.155.147 \t {}", Ip2regionAnalysis.getInstance().getIpInfoBean("124.205.155.147"));
        // 批量解析,返回字典數(shù)據(jù):ip:解析信息
        final HashSet<String> ipSet = CollUtil.newHashSet(
                "47.92.113.71", "221.226.75.86", "124.205.155.155",
                "47.57.188.208", "121.8.215.106", "121.8.215.106"
        );
        Dict dict = Ip2regionAnalysis.getInstance().getIpInfo(ipSet);
        log.info("{}", dict.toString());
        log.info("{}\t{}", "121.8.215.106", dict.getStr("121.8.215.106"));
    }
}

測(cè)試輸出

14:19:12.791 [main] DEBUG cn.hutool.log.LogFactory - Use [Slf4j] Logger As Default.
14:19:14.150 [main] INFO util.Ip2regionAnalysis - 下載IP數(shù)據(jù)庫文件...
14:19:14.633 [main] INFO util.Ip2regionAnalysis - IP數(shù)據(jù)庫文件下載成功,數(shù)據(jù)庫文件大小[8.33MB]
14:19:14.645 [main] INFO util.Ip2regionAnalysis - 121.8.215.106      IpInfo(country=中國, region=0, province=廣東省, city=廣州市, isp=電信)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 183.247.152.98      IpInfo(country=中國, region=0, province=浙江省, city=杭州市, isp=移動(dòng))
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 14.29.139.251      IpInfo(country=中國, region=0, province=廣東省, city=深圳市, isp=電信)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 183.247.152.98      IpInfo(country=中國, region=0, province=浙江省, city=杭州市, isp=移動(dòng))
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 27.105.130.93      IpInfo(country=中國, region=0, province=臺(tái)灣省, city=臺(tái)北, isp=So-Net)
14:19:14.646 [main] INFO util.Ip2regionAnalysis - 124.205.155.147      IpInfo(country=中國, region=0, province=北京, city=北京市, isp=鵬博士)
14:19:14.648 [main] INFO util.Ip2regionAnalysis - {221.226.75.86=中國|0|江蘇省|南京市|電信, 47.57.188.208=中國|0|香港|0|阿里云, 47.92.113.71=中國|0|河北省|張家口市|阿里云, 121.8.215.106=中國|0|廣東省|廣州市|電信, 124.205.155.155=中國|0|北京|北京市|鵬博士}
14:19:14.682 [main] INFO util.Ip2regionAnalysis - 121.8.215.106    中國|0|廣東省|廣州市|電信

在第一次調(diào)用getInstance時(shí)會(huì)去下載數(shù)據(jù)庫文件會(huì)比較耗時(shí),其他后面的操作就很快了,基本上幾毫秒就查詢到了。

所以如果嫌第一次慢的,可以在程序啟動(dòng)完成后手動(dòng)調(diào)用,預(yù)熱一下,在實(shí)際業(yè)務(wù)就會(huì)使用緩存的數(shù)據(jù)庫了。

實(shí)際使用

在項(xiàng)目中我編寫了一個(gè) CommonController.java ,然后使用編寫的類提供了一個(gè)接口,用于獲取IP的信息。

import cn.hutool.extra.servlet.ServletUtil;
import com.yunding.vote.common.api.CommonResult;
import com.yunding.vote.common.limiter.RInterfaceLimit;
import com.yunding.vote.domain.IpInfo;
import com.yunding.vote.util.Ip2regionAnalysis;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/**
 * 公共控制層,該類方法不會(huì)記錄日志
 */
@RestController
@Api(tags = "公共控制層", description = "公共控制層")
@RequestMapping("/common")
@Slf4j
public class CommonController {
    @Resource
    private HttpServletRequest request;
    @ApiOperation("獲取IP的信息,100QPS")
    @GetMapping(value = "/ipInfo/{ip}")
    @RInterfaceLimit(rate = 100)
    public CommonResult<IpInfo> getIpInfo(@PathVariable String ip) {
        String clientIp = ServletUtil.getClientIP(request);
        IpInfo ipInfo = Ip2regionAnalysis.getInstance().getIpInfoBean(ip);
        return CommonResult.success(ipInfo);
    }
}

上面這個(gè)類只是告訴大家是怎么使用Ip2regionAnalysis這個(gè)類的,大家根據(jù)自己的項(xiàng)目自行調(diào)整。

GET http://127.0.0.1:8080/api/v1/common/ipInfo/121.8.215.106

>>>
{
  "code": 200,
  "data": {
    "country": "中國",
    "region": 0,
    "province": "廣東省",
    "city": "廣州市",
    "isp": "電信"
  },
  "message": "操作成功"
}

到此這篇關(guān)于JAVA使用Ip2region獲取IP定位信息的文章就介紹到這了,更多相關(guān)java獲取IP定位信息內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)的小時(shí)鐘示例分享

    java實(shí)現(xiàn)的小時(shí)鐘示例分享

    這篇文章主要介紹了java實(shí)現(xiàn)的小時(shí)鐘示例,需要的朋友可以參考下
    2014-02-02
  • JDK21新特性Record?Patterns記錄模式詳解(最新推薦)

    JDK21新特性Record?Patterns記錄模式詳解(最新推薦)

    這篇文章主要介紹了JDK21新特性Record?Patterns記錄模式詳解,本JEP建立在Pattern?Matching?for?instanceof(JEP?394)的基礎(chǔ)上,該功能已在JDK?16中發(fā)布,它與Pattern?Matching?for?switch(JEP?441)共同演進(jìn),需要的朋友可以參考下
    2023-09-09
  • SpringBoot中到底該如何解決跨域問題

    SpringBoot中到底該如何解決跨域問題

    跨域問題更是老生常談,隨便用標(biāo)題去google或百度一下,能搜出一大片解決方案,這篇文章主要給大家介紹了關(guān)于SpringBoot中到底該如何解決跨域問題的相關(guān)資料,需要的朋友可以參考下
    2022-02-02
  • Java集合的定義與Collection類使用詳解

    Java集合的定義與Collection類使用詳解

    這篇文章主要介紹了Java集合的定義及Collection工具類使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • 在Java項(xiàng)目中實(shí)現(xiàn)日志輸出的技巧分享

    在Java項(xiàng)目中實(shí)現(xiàn)日志輸出的技巧分享

    日志是開發(fā)過程中不可或缺的一部分,它可以幫助我們追蹤代碼的執(zhí)行過程、排查問題以及監(jiān)控系統(tǒng)運(yùn)行狀況,然而,大多數(shù)開發(fā)人員在編寫日志時(shí)往往只關(guān)注于輸出必要的信息,而忽略了日志的可讀性和美觀性,本文將介紹如何在Java項(xiàng)目中實(shí)現(xiàn)漂亮的日志輸出
    2023-10-10
  • java用字節(jié)數(shù)組解決FileInputStream讀取漢字出現(xiàn)亂碼問題

    java用字節(jié)數(shù)組解決FileInputStream讀取漢字出現(xiàn)亂碼問題

    這篇文章主要介紹了java用字節(jié)數(shù)組解決FileInputStream讀取漢字出現(xiàn)亂碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    教你怎么用SpringBoot+Mybati-Plus快速搭建代碼

    Mybatis自身通過了逆向工程來幫助我們快速生成代碼,但Mybatis-plus卻更加強(qiáng)大,不僅僅可以生成dao,pojo,mapper,還有基本的controller和service層代碼,接下來我們來寫一個(gè)簡(jiǎn)單的人門案例是看看如何mybatis-plus是怎么實(shí)現(xiàn)的,需要的朋友可以參考下
    2021-06-06
  • java 數(shù)學(xué)計(jì)算的具體使用

    java 數(shù)學(xué)計(jì)算的具體使用

    這篇文章主要介紹了java 數(shù)學(xué)計(jì)算的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Spring Boot應(yīng)用監(jiān)控的實(shí)戰(zhàn)教程

    Spring Boot應(yīng)用監(jiān)控的實(shí)戰(zhàn)教程

    Spring Boot 提供運(yùn)行時(shí)的應(yīng)用監(jiān)控和管理功能,下面這篇文章主要給大家介紹了關(guān)于Spring Boot應(yīng)用監(jiān)控的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • 實(shí)例詳解SpringMVC入門使用

    實(shí)例詳解SpringMVC入門使用

    大家好,本篇文章主要講的是實(shí)例詳解SpringMVC入門使用,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12

最新評(píng)論

吉木萨尔县| 宁海县| 石城县| 光山县| 临西县| 双牌县| 温州市| 涡阳县| 区。| 沂水县| 嘉义市| 额尔古纳市| 宜昌市| 贵德县| 游戏| 广德县| 赤峰市| 江都市| 清丰县| 内乡县| 德阳市| 文成县| 邯郸县| 临漳县| 宜川县| 峨山| 榆社县| 莲花县| 襄樊市| 东宁县| 青阳县| 荃湾区| 巴青县| 凌云县| 株洲市| 东港市| 布尔津县| 永清县| 朝阳区| 积石山| 宁都县|