根据IP地址获取归属地

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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/488638.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ElasticSearch之数据建模

写在前面 本文看下es数据建模相关的内容。 1&#xff1a;什么是数据建模 数据建模是对真实数据的一种抽象&#xff0c;最终映射为计算机形式的表现。其包括如下三个阶段&#xff1a; 1&#xff1a;概念模型 2&#xff1a;逻辑模型 3&#xff1a;数据模型2&#xff1a;es数据…

案例分享:F5助力车企打造智能高效自动化应用

纵观当下的汽车市场&#xff0c;智能汽车百花齐放。自动驾驶、车载娱乐、实时3D地图等实现人机互动的出行场景&#xff0c;解锁着全新的出行方式。然而得到独特而先进的智能用车体验&#xff0c;离不开持续而深入的汽车应用变革。那么怎样打造智能高效的自动化应用呢&#xff1…

JavaWeb后端——HTTP协议/Tomcat

HTTP HTTP协议&#xff1a;无状态&#xff0c;对事务处理没有记忆能力。每次请求-响应都是独立的。后一次请求不会记录前一次请求数据。缺点&#xff1a;多次请求之间不能共享数据&#xff0c;优点&#xff1a;速度快。 HTTP协议请求报文&#xff1a; HTTP协议响应报文&#x…

(MATLAB)第二十一章 Simulink仿真设计初步

Simulink是MATLAB的重要组成部分&#xff0c;可以非常容易地实现可视化建模&#xff0c;并把理论研究和工程实践有机地结合在一起&#xff0c;不需要书写大量程序&#xff0c;只需要使用鼠标和键盘对已有模块进行简单的操作和设置。 21.1 Simulink简介 Simulink是MATLAB软件的…

一、Java开发环境搭建-----系统类的简单使用

JavadocAPI文档练习&#xff1a; 1、Date类的使用——代码实战 Date类为日期类&#xff0c;是Java中和日期相关的一个类&#xff0c;如下将日期做一个简单的介绍。 package com.kangning.web.controller.common;import java.util.Date;public class DateDemo1 {public static…

SAP/ERP系统PP模块常用增强之二:报表COOIS增加字段

SAP/PP模块中的COOIS报表(订单信息系统)是最常用的标准报表之一,它可以查询有关生产订单的完整信息,但实际项目实施中也会经常遇到这个报表增强需求,一般要求增加一些产品相关的一些额外信息。 SAP系统为此类需求预留第三代BADI增强出口,可以非常方便的实现在COOIS报表中…

水泊梁山108小酒坛之小李广花荣

小李广花荣&#xff0c;是中国著名小说《水浒传》中的108将之一&#xff0c;有“百步穿杨”的功夫。在梁山泊英雄中排行第九&#xff0c;为马军八虎骑兼先锋使之首。原是清风寨副知寨&#xff0c;使一杆银枪&#xff0c;一张弓射遍天下无敌手&#xff0c;生得一双俊目&#xff…

谈谈消息队列

这篇文章我们来聊聊消息队列。我一直在想&#xff0c;能不能用一篇文章就把消息队列的所有内容给串联起来。然后&#xff0c;之后每次看到这篇文章的时候&#xff0c;我就能够立马回忆起来这个大知识的所有知识点。所以我想尝试一下用这种长文的方式&#xff0c;将我自己对于消…

财富池指标公式--通达信资金进场买入提示指标公式

1、“准备现金”信号出现&#xff0c;可开始关注该个股&#xff0c;等待合适价位介入&#xff0c;较为激进的投资者也可在此时介入&#xff0c;更稳健的做法是&#xff0c;等到“买入股票”信号出现后再介入。 2、“见顶清仓”信号出现&#xff0c;预示着即将见顶&#xff0c;是…

Matlab从入门到精通课程

教程介绍 MATLAB是美国MathWorks公司出品的商业数学软件&#xff0c;用于数据分析、无线通信、深度学习、图像处理与计算机视觉、信号处理、量化金融与风险管理、机器人&#xff0c;控制系统等领域。 学习地址 链接&#xff1a;https://pan.baidu.com/s/1PxGarBwQusMzwPVqcE…

【JavaScript】JavaScript 程序流程控制 ⑥ ( while 循环概念 | while 循环语法结构 )

文章目录 一、while 循环1、while 循环概念2、while 循环语法结构 二、while 循环 - 代码示例1、打印数字2、计算 1 - 10 之和 一、while 循环 1、while 循环概念 在 JavaScript 中 , while 循环 是一种 " 循环控制语句 " , 使用该语句就可以 重复执行一段代码块 , …

如何使用 ArcGIS Pro 制作三维建筑

三维地图已经逐渐成为未来地图的趋势&#xff0c;对于大范围应用&#xff0c;只需要普通的建筑体块就行&#xff0c;如果有高程数据&#xff0c;还可以结合地形进行显示&#xff0c;这里为大家介绍一下 ArcGIS Pro 制作三维建筑的方法&#xff0c;希望能对你有所帮助。 数据来…

Kimi是什么?免费Kimi chat介绍

1. Kimi是什么&#xff1f; Kimi是由月之暗面科技有限公司&#xff08;Moonshot AI&#xff09;开发的人工智能助手&#xff0c;专注于提供高质量的对话和信息处理服务。 月之暗面公司创立于2023年3月&#xff0c;创始团队核心成员参与了Google Gemini、Google Bard、盘古NLP、…

Java面试篇:Redis使用场景问题(缓存穿透,缓存击穿,缓存雪崩,双写一致性,Redis持久化,数据过期策略,数据淘汰策略)

目录 1.缓存穿透解决方案一:缓存空数据解决方案二&#xff1a;布隆过滤器 2.缓存击穿解决方案一:互斥锁解决方案二:设置当前key逻辑过期 3.缓存雪崩1.给不同的Key的TTL添加随机值2.利用Redis集群提高服务的可用性3.给缓存业务添加降级限流策略4.给业务添加多级缓存 4.双写一致性…

✮✮✮宁波CE认证,CE认证,CE产品检测✮✮✮

✮✮✮&#x1f308;宁波CE认证&#xff0c;&#x1f308;CE认证&#xff0c;&#x1f308;CE产品检测&#x1f308;✮✮✮ ❀热点&#xff1a;&#x1f618;CE认证什么意思 ❀优势&#xff1a;&#x1f61c;CE认证的目的 ✎&#x1f352;CE认证定义和目的 ✎&#x1f350;CE认…

李宏毅深度强化学习导论——演员-评论员

引言 本文主要介绍演员-评论员(Actor-Critic)算法。 Critic 给定Actor θ \theta θ&#xff0c;Critic评估当观测到 s s s(或进一步地采取行动 a a a)的好坏。 价值函数(Value function)&#xff0c;记为 V θ ( s ) V^\theta(s) Vθ(s)&#xff0c;就是一种Critic。 它的…

蓝桥杯刷题(十四)

1.小平方 代码 n int(input()) count0 def f(x)->bool: # 判断条件return True if x**2%n<n/2 else False for i in range(1,n): # 遍历[1,n-1]&#xff0c;符合题意计数加一if f(i):count1 print(count)2.3的倍数 代码 a int(input()) b int(input()) c int(input…

【python】flask各种版本的项目,终端命令运行方式的实现

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Java:ArrayList与顺序表

一、线性表 线性表是n个具有相同特征的数据元素的有限序列&#xff0c;它是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表有&#xff1a;顺序表、链表、栈、队列...... 如图&#xff1a;顺序表与链表的区别看了标题的伙伴就应该知道&#xff0c;我们这次要讲解的主…

【浏览器渲染-输入Url到页面渲染全流程】

概述 在面试题中有一道经典面试题就是浏览器输入url之后发送了什么&#xff0c;看了下网上的大多数文章都感觉不太全&#xff0c;所以这里梳理了比较全的流程&#xff0c;如果有误&#xff0c;欢迎评论指正。本文大致是从以下内容概览入手&#xff0c;有需要的可以跳转到感兴趣…
最新文章