根据IP地址获取归属地

本文介绍了如何在Java应用中使用Ip2region离线IP地址定位库来避免API服务不稳定的问题,详细讲解了如何下载和加载数据库文件,以及创建工具类进行IP解析。还提到了解决打包时xdb文件被压缩导致无法读取的问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IP获取归属地,通过地址库获取

如果使用API接口获取,可能会出现服务挂了,或者服务地址不提供服务了等问题。而采用本地地址库就没有这些问题。
本文采用离线IP地址定位库 Ip2region,Ip2region是一个离线IP地址定位库,微秒的查询时间。

实现步骤

  1. 访问官网github地址:https://github.com/lionsoul2014/ip2region
    在这里插入图片描述
  2. 找到data目录下的:ip2region.xdb文件下载下来
    在这里插入图片描述
  3. 把ip2region.xdb文件放在resources目录下

在这里插入图片描述

  1. 在模块中引入maven依赖
<!--解析ip地址-->
<dependency>
  <groupId>org.lionsoul</groupId>
  <artifactId>ip2region</artifactId>
  <version>2.7.0</version>
</dependency>
  1. 获取归属地工具类
package com.sinosoft.springbootplus.util;

import cn.hutool.core.io.resource.ResourceUtil;
import com.sinosoft.springbootplus.common.api.ApiCode;
import com.sinosoft.springbootplus.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.flywaydb.core.internal.util.FileCopyUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * ip解析工具
 *
 */
@Slf4j
public class IpParseUtil {

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

    static {
        try (InputStream inputStream = new ClassPathResource("ip2region.xdb").getInputStream()){
            byte[] cBuff = IOUtils.toByteArray(inputStream);
            SEARCHER = Searcher.newWithBuffer(cBuff);
            log.info("加载了ip2region.xdb文件,Searcher初始化完成!");
        } catch (Exception e) {
            log.error("初始化ip2region.xdb文件失败,报错信息:[{}]", e.getMessage(), e);
            throw new BusinessException(ApiCode.SYSTEM_EXCEPTION);
        }
    }
    
    /**
     * 解析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 BusinessException(ApiCode.SYSTEM_EXCEPTION);
        }
    }

    /**
     * 自定义解析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) {
                    if ("0".equals(split[i])) {
                        split[i] = "——";
                    }
                    regionList.add(split[i]);
                }
            }
            //关闭资源
            SEARCHER.close();
        } catch (Exception e) {
            log.error("根据ip解析地址失败,ip:[{}],index[{}],报错信息:[{}]", ip, index, e.getMessage(), e);
            throw new BusinessException(ApiCode.SYSTEM_EXCEPTION);
        }
        return regionList;
    }
}

这里Searcher引用的是仓库里面的检索方法,到这里就完成了可以获取到ip对应的归属地。

  1. 测试类
package com.sinosoft.springbootplus;

import com.sinosoft.springbootplus.util.IpParseUtil;

import java.util.List;

/**
 * @author lsh
 * @date 2024/3/21
 */
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);
    }
}

结果
在这里插入图片描述

遇到的问题

包后读取到的文件流大小发生变化,无法根据ip识别到对应的地址信息。
1、正常读取到的文件大小如下图
在这里插入图片描述
打成jar包后,在依赖项目中运行,读取到的文件流如下图
在这里插入图片描述
2、出现的原因是打包时文件被压缩了
3、解决办法,在pom文件中增加下面的配置,打包时不压缩后缀为xdb格式的文件

<plugins>

            <!--
            避免在resource是目下,后缀为 xdb文件被压缩,导致不可以读,此处做排除操作。
            如果有新的类型的文件可以再后边追加
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>xdb</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
            </plugin>

        </plugins>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值