Java通过Ip2region实现IP定位

我们在一些短视频平台上可以看到,视频作者或评论区可以显示IP地址,这其实就是根据IP获取到的我们可以通过一些在线网站就可以看到我们当前的公网IP和IP定位,最近有个需求也需要通过请求获取客户端的IP和IP的定位,于是通过一系列的百度,最终选择使用Ip2region这个工具库来进行定位

 Ip2region简介

Ip2region是一个开源工具库,是一种用于IP地址定位的工具。 它是基于B树数据结构的数据库,可用于将IP地址转换为国家、省、市、区县等信息。 使用Ip2region工具,您可以轻松地查找某个IP地址所在的区域信息,从而帮助您进行定位和分析。

目前Ip2region有1.0和2.0两个版本,p2region 1.0和Ip2region 2.0之间的主要区别在于数据的更新频率和精度。 Ip2region 2.0在原有版本的基础上增加了更多的数据,例如更详细的地图信息和更准确的IP地址定位。 Ip2region 2.0的数据更新频率也更高,这意味着它将提供更精确的信息。此外, Ip2region 2.0还提供了Java、Python和PHP等语言的版本,这使得它更加适用于不同类型的应用程序。

GitHub地址(CSDN镜像地址,非原地址):https://gitcode.net/mirrors/lionsoul2014/ip2region

 Ip2region使用

前面提到Ip2region分为1.0和2.0两个版本,此处我是用的是2.0版本,如需1.0版本此文章并不适用,可以参考如下文章

(153条消息) Java根据ip地址获取归属地_java通过ip地址获取地区_java技术媛的博客-CSDN博客

 Ip2region2.0版本引入依赖

2.7.0是当前最新版本,使用Ip2region2.0引入2.6.0版本及以上应该是都可以的

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

下载ip2region.xdb文件

下载链接;https://gitcode.net/mirrors/lionsoul2014/ip2region/-/blob/master/data/ip2region.xdb

 如果链接失效:进入上文github地址然后选在data文件夹,里面就有ip2region.xdb文件

 下载后将其放在resources文件夹下,注意在pom文件里添加排除配置,防止maven将文件编译

<plugin>
    <configuration>
        <nonFilteredFileExtensions>
            <nonFilteredFileExtension>xdb</nonFilteredFileExtension>
        </nonFilteredFileExtensions>
    </configuration>
</plugin>

Searcher介绍

ip2region核心类就是Searcher,在2.0的版本中它有三种创建方式,三种方式使用方式不太一样,接下来逐一介绍

newWithFileOnly(String dbPath)

此种创建方式,只有一个参数,顾名思义,我们可以知道入参其实就是ip2region.xdb文件的路径,此种创建方式是最基础的创建方式,不支持并发,每次创建都需要进行一次IO,读取本地ip2region.xdb文件

newWithVectorIndex(String dbPath, byte[] vectorIndex)

此种创建方式多出来一个vectorIndex参数,它是一个字节数组我们可以提前从 xdb 文件中加载出来 VectorIndex 数据,然后全局缓存,每次创建 Searcher 对象的时候使用全局的 VectorIndex 缓存可以减少一次固定的 IO 操作,从而加速查询,减少 IO 压力。此种方式也不支持并发,每个线程需要重新new一个Searcher对象

newWithBuffer(byte[] cBuff)

此种创建方式只有一个cBuff参数,它可以预先加载整个 ip2region.xdb 的数据到内存,然后基于这个数据创建查询对象来实现完全基于文件的查询无IO压力,而且仅占用11M内存,最重要的是它支持并发,全局只需要创建一次即可,也是查询效率最高的一种方法,下面我自己封装了一个工具类,就是采用的这种方式

工具类代码

/**
 * ip解析工具
 *
 * @author zzt
 * @version v1.0.0
 * @date 2023/6/9 9:26
 */
@Slf4j
public class IpParseUtil {

    /**
     * 将整个xdb文件加载到内存中(11M左右),此种创建方式支持多线程,因此只需要加载一次
     */
    private final static Searcher SEARCHER;

    static {
        try {
            ClassPathResource resource = new ClassPathResource("ip2region.xdb");
            //获取真实文件路径
            String path = resource.getURL().getPath();
            byte[] cBuff = Searcher.loadContentFromFile(path);
            SEARCHER = Searcher.newWithBuffer(cBuff);
            log.info("加载了ip2region.xdb文件,Searcher初始化完成!");
        } catch (Exception e) {
            log.error("初始化ip2region.xdb文件失败,报错信息:[{}]", e.getMessage(), e);
            throw new RuntimeException("系统异常!");
        }
    }


    /**
     * 解析ip地址
     *
     * @param ipStr 字符串类型ip 例:192.168.0.1
     * @return 返回结果形式(国家|区域|省份|城市|ISP) 例 [中国, 0, 河北省, 衡水市, 电信]
     */
    public static List<String> parse(@NotBlank String ipStr) {
        return parse(ipStr, null);
    }

    /**
     * 自定义解析ip地址
     *
     * @param ipStr ip 字符串类型ip 例:1970753539(经过转换后的)
     * @param index 想要获取的区间 例如:只想获取 省,市 index = [2,3]
     * @return 返回结果例 [北京,北京市]
     */
    public static List<String> parse(@NotBlank String ipStr, int[] index) {
        try {
            long ip = Searcher.checkIP(ipStr);
            return parse(ip, index);
        } catch (Exception e) {
            log.error("ip解析为long错误,ipStr:[{}],错误信息:[{}]", ipStr, e.getMessage(), e);
            throw new RuntimeException("系统异常!");
        }
    }

    /**
     * 自定义解析ip地址
     *
     * @param ip    ip Long类型ip
     * @param index 想要获取的区间 例如:只想获取 省,市 index = [2,3]
     * @return 返回结果例 [河北省, 衡水市]
     */
    public static List<String> parse(@NotNull Long ip, int[] index) {
        //获取xdb文件资源
        List<String> regionList = new ArrayList<>();
        try {
            String region = SEARCHER.search(ip);
            String[] split = region.split("\\|");
            if (index == null) {
                regionList = Arrays.asList(split);
            } else {
                for (int i : index) {
                    regionList.add(split[i]);
                }
            }
            //关闭资源
            SEARCHER.close();
        } catch (Exception e) {
            log.error("根据ip解析地址失败,ip:[{}],index[{}],报错信息:[{}]", ip, index, e.getMessage(), e);
            throw new RuntimeException("系统异常!");
        }
        return regionList;
    }
}

简单测试 

public class IPTest {
    public static void main(String[] args) {
        //只获取省,市
        int[] index = {2, 3};
        List<String> parse = IpParseUtil.parse("222.223.145.133", index);
        System.out.println(parse);
    }
}

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ip2region是一个准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java,php,c,python,nodejs,golang,c#等查询绑定和Binary,B树,内存三种查询算法。 Ip2region特性: 一、99.9%准确率 数据聚合了一些知名ip到地名查询提供商的数据,这些是他们官方的的准确率,经测试着实比经典的纯真IP定位准确一些。 二、标准化的数据格式 每条ip数据段都固定了格式: _城市Id|国家|区域|省份|城市|ISP_ 只有中国的数据精确到了城市,其他国家有部分数据只能定位到国家,后前的选项全部是0,已经包含了全部你能查到的大大小小的国家(请忽略前面的城市Id,个人项目需求)。 三、体积小 包含了全部的IP,生成的数据库文件ip2region.db只有几MB,最小的版本只有1.5MB,随着数据的详细度增加数据库的大小也慢慢增大,目前还没超过8MB。 四、查询速度快 全部的查询客户端单次查询都在0.x毫秒级别,内置了三种查询算法: 1.memory算法:整个数据库全部载入内存,单次查询都在0.1x毫秒内,C语言的客户端单次查询在0.00x毫秒级别。 2.binary算法:基于二分查找,基于ip2region.db文件,不需要载入内存,单次查询在0.x毫秒级别。 3.b-tree算法:基于btree算法,基于ip2region.db文件,不需要载入内存,单词查询在0.x毫秒级别,比binary算法更快。 任何客户端b-tree都比binary算法快,当然memory算法固然是最快的! 五、多查询客户端的支持 已经集成的客户端有:java、C#、php、c、python、nodejs、php扩展(php5和php7)、golang、rust、lua、lua_c,nginx。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值