SpringBoot整合Ip2region获取IP地址和定位

news2024/11/26 8:23:22

1.Ip2region的介绍

1.1.Ip2region 是什么

ip2region v2.0 - 是一个离线IP地址定位库和IP定位数据管理框架,10微秒级别的查询效率,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现 。

1.2.Ip2region 特性

1.2.1 标准化的数据格式

每个 ip 数据段的 region 信息都固定了格式:国家|区域|省份|城市|ISP,只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0。

1.2.2.数据去重和压缩

xdb 格式生成程序会自动去重和压缩部分数据,默认的全部 IP 数据,生成的 ip2region.xdb 数据库是 11MiB,随着数据的详细度增加数据库的大小也慢慢增大。

1.2.3.极速查询响应

即使是完全基于 xdb 文件的查询,单次查询响应时间在十微秒级别,可通过如下两种方式开启内存加速查询:

  • vIndex 索引缓存 :使用固定的 512KiB 的内存空间缓存 vector index 数据,减少一次 IO 磁盘操作,保持平均查询效率稳定在10-20微秒之间。
  • xdb 整个文件缓存:将整个 xdb 文件全部加载到内存,内存占用等同于 xdb 文件大小,无磁盘 IO 操作,保持微秒级别的查询效率。

1.2.4.IP 数据管理框架

v2.0 格式的 xdb 支持亿级别的 IP 数据段行数,region 信息也可以完全自定义,例如:你可以在 region 中追加特定业务需求的数据,例如:GPS信息/国际统一地域信息编码/邮编等。也就是你完全可以使用 ip2region 来管理你自己的 IP 定位数据。

2.Java方式

2.1.下载ip2region.xdb

狮子的魂 / ip2region
下载完后放到工程的resources目录下
在这里插入图片描述

2.2.maven仓库

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

2.3.代码

import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.FileCopyUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 晓风残月Lx
 * @date 2023/4/11 19:25
 */
public class IpUtils {
    private static final Logger logger = LoggerFactory.getLogger(IpUtils.class);
    private final static String localIp = "127.0.0.1";

    private static Searcher searcher = null;

    /**
     *   在服务启动时加载 ip2region.db 到内存中
     *   解决打包jar后找不到 ip2region.db 的问题
     */
    static {
        try {
            InputStream ris = IpUtils.class.getResourceAsStream("/ip2region/ip2region.xdb");
            byte[] dbBinStr = FileCopyUtils.copyToByteArray(ris);
            searcher = Searcher.newWithBuffer(dbBinStr);
            //注意:不能使用文件类型,打成jar包后,会找不到文件
            logger.debug("缓存成功!!!!");
        } catch (IOException e) {
            logger.error("解析ip地址失败,无法创建搜索器: {}", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取用户真实IP地址,不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 参考文章: http://developer.51cto.com/art/201111/305181.htm
     *
     * 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值,究竟哪个才是真正的用户端的真实IP呢?
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     *
     * 如:X-Forwarded-For:192.168.1.110, 192.168.1.120, 192.168.1.130,
     * 192.168.1.100
     *
     * 用户真实IP为: 192.168.1.110
     *
     * @param request
     * @return
     */
    public static String getIp(HttpServletRequest request) {
        String ipAddress;
        try {
            // 以下两个获取在k8s中,将真实的客户端IP,放到了x-Original-Forwarded-For。而将WAF的回源地址放到了 x-Forwarded-For了。
            ipAddress = request.getHeader("X-Original-Forwarded-For");
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("X-Forwarded-For");
            }

            //获取nginx等代理的ip
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("x-forwarded-for");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ipAddress == null || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
            }

            // 2.如果没有转发的ip,则取当前通信的请求端的ip(兼容k8s集群获取ip)
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                // 如果是127.0.0.1,则取本地真实ip
                if (localIp.equals(ipAddress)) {
                    // 根据网卡取本机配置的IP
                    InetAddress inet = null;
                    try {
                        inet = InetAddress.getLocalHost();
                        ipAddress = inet.getHostAddress();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                }
            }

            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if (ipAddress != null && ipAddress.length() > 15) {
                // = 15
                if (ipAddress.indexOf(",") > 0) {
                    ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
                }
            }
        } catch (Exception e) {
            logger.error("解析请求IP失败", e);
            ipAddress = "";
        }
        return "0:0:0:0:0:0:0:1".equals(ipAddress) ? localIp : ipAddress;
    }

    /**
     * 获取访问设备
     * @param request
     * @return
     */
    public static UserAgent getUserAgent(HttpServletRequest request) {
        return UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
    }

    /**
     * 根据ip获取 城市信息
     * @param ipAddress
     * @return
     */
    public static String getCityInfo(String ipAddress) {
        String cityInfo = null;
        try {
            return searcher.search(ipAddress);
        } catch (Exception e) {
            logger.error("搜索:{} 失败: {}",ipAddress, e);
        }
        return null;
    }

    /**
     * 根据ip2region解析ip地址
     * @param ip ip地址
     * @return 解析后的ip地址信息
     */
    public static String getIp2region(String ip)  {

        if(searcher == null){
            logger.error("Error: DbSearcher is null");
            return null;
        }

        try {
            String ipInfo = searcher.search(ip);
            if (!StringUtils.isEmpty(ipInfo)) {
                ipInfo = ipInfo.replace("|0", "");
                ipInfo = ipInfo.replace("0|", "");
            }
            return ipInfo;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取IP地址
     *
     * @return 本地IP地址
     */
    public static String getHostIp(){
        try{
            return InetAddress.getLocalHost().getHostAddress();
        }catch (UnknownHostException e){
        }
        return localIp;
    }


    /**
     * 获取主机名
     *
     * @return 本地主机名
     */
    public static String getHostName(){
        try{
            return InetAddress.getLocalHost().getHostName();
        } catch (UnknownHostException e) {
        }
        return "未知";
    }
}

测试类

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class XfcyBlogApplicationTests {
    @Test
    void ipTest() {
        String cityInfo = IpUtils.getCityInfo("120.36.213.176");
        String cityInfo1 = IpUtils.getCityInfo("10.6.152.27");
        System.out.println(cityInfo);
        System.out.println(cityInfo1);
    }
}

第一个IP是网上找的IP进行测试
第二个IP是自己本机IP进行测试
在这里插入图片描述
国家|区域|省份|城市|ISP

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录解决Android Studio下载gradle超时问题

大三学生&#xff0c;2023年3月19号晚&#xff0c;首次下载Android Studio2022版本并新建项目&#xff0c;发现在下载gradle总是连接超时&#xff0c;舍友则没有这个问题&#xff0c;用的是同一个安装包。 查阅文献太多&#xff0c;忘记都有哪些了&#xff0c;就不列出来了&…

MySQL 课后习题解析与笔记——学生选课数据库相关操作

文章目录 &#x1f4cb;前言&#x1f3af;题目解析1️⃣创建数据库2️⃣创建表&#x1f4d1;Student 表&#x1f4d1;Course 表&#x1f4d1;SC 表 &#x1f3af;完整答案&#x1f4dd;最后 &#x1f4cb;前言 这篇文章记录一下帮助粉丝朋友一起学习解决的 MySQL 课后习题&…

5款AI应用让你全面感受人工智能的魅力

“ AI 的出现就像燃气机和蒸汽机一样&#xff0c;极大地提高了生产力。” chatGPT ChatGPT 是由 OpenAI 公司开发的一种大型语言模型。 OpenAI 公司成立于 2015年&#xff0c;早期马斯克是该公司的创始人之一。 自 2018 年推出 GTP-1 以来&#xff0c;OpenAI 已经推出了 GPT-…

Power BI Visuals - Candlestick (K线图) 介绍文档

注&#xff1a;本文最初发布于 d-bi.gitee.io &#xff08;2020年4月&#xff09;, 2023年6月迁移至CSDN 注:本文将简要介绍新的Power BI可视化–Candlestick的使用方法 简介 Candlestick是由本人(Davis ZHANG)使用R语言开发的Power BI可视化, 它将在数日之后(取决于审核的进…

chatgpt赋能python:Python平均值:让你的数据更有说服力

Python平均值&#xff1a;让你的数据更有说服力 作为一个有10年Python编程经验的工程师&#xff0c;我非常熟悉Python程序的各种应用。其中&#xff0c;计算平均值是数据分析中最常用的计算方法之一&#xff0c;而Python作为一种广泛应用的语言&#xff0c;也可以轻松地处理平…

k8s网络模型

前言 通过《Linux网络原理》我们已据备了一定的理论知识。k8s是怎么构建网络模型的呢&#xff1f; 基础知识 交换机和路由器都是网络中常见的设备&#xff0c;它们在网络通信中扮演不同的角色。 交换机&#xff08;Switch&#xff09;是一种用于构建局域网&#xff08;LAN&a…

11 - 守护进程深度分析

---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接&#xff1a;&#xff08;更新中&#xff09;Linux系统编程训练营 - 目录 文章目录 1. 会话与终端的关联1.1 思考1.2 新会话关联控制终端的方法1.3 一些相关推论1.4 一些想法1.5 编程实验&#xff1a;会话与终端 2. 守护进程…

SpringSecurity自定义认证

一. 前言 ​ 学习了SpringSecurity的使用&#xff0c;以及跟着源码分析了一遍认证流程&#xff0c;掌握了这个登录认证流程&#xff0c;才能更方便我们做自定义操作。 ​ 下面我们来学习下怎么实现多种登录方式&#xff0c;比如新增加一种邮箱验证码登录的形式&#xff0c;但…

chatgpt赋能python:用Python建立Pipeline-优化你的数据处理流程

用Python建立Pipeline - 优化你的数据处理流程 如果你是一位数据科学家或是数据工程师&#xff0c;那么你一定知道数据处理流程的重要性。数据流程不只是数据的处理和清洗&#xff0c;还包括数据来源的获取以及对数据进行可视化、建模和验证。这个流程可以十分复杂&#xff0c…

solr快速上手:实现从mysql定时自动同步数据(六)

0. 引言 上一章节我们讲解了从msyql同步数据到solr&#xff0c;但是我们每次同步都需要在solr-admin中点击同步按钮&#xff0c;这在生产环境中肯定是不可行的&#xff0c;那么solr是否支持自动化同步了&#xff0c;答案当然是可以&#xff0c;我们今天继续来探索如何实现solr…

虚拟机安装和配置红帽企业版 7.4 操作系统及相关设置

虚拟机安装和配置红帽企业版 7.4 操作系统及相关设置 当安装红帽企业版 7.4 操作系统时&#xff0c;可以按照以下步骤进行配置和设置&#xff1a; 使用 VM16.0 安装软件&#xff0c;打开虚拟机管理程序&#xff0c;并选择创建新的虚拟机。在创建虚拟机的过程中&#xff0c;选…

ChatGPT在线网页版和接口

chat gpt能写公众号文章吗 ChatGPT是一种强大的自然语言生成技术&#xff0c;它可以用来自动生成大量的、质量较高的文本。根据OpenAI官方的演示和使用案例&#xff0c;ChatGPT已经被用于文本摘要、对话生成、语言翻译、文本分类等多种应用场景。 然而&#xff0c;ChatGPT作为…

文本三剑客之 awk

awk Linux/UNIX 系统中&#xff0c;awk 是一个功能强大的编辑工具。逐行读取输入文本 以空格作为分割符&#xff0c;多个空格他会自动压缩成一个空格 AWK信息的读入也是逐行指定的匹配模式进行查找&#xff0c;对符合条件的内容进行格式化输出或者过滤处理. 1按照命令找指定…

用户档案PDF报表

用户档案PDF报表 理解数据填充的两种方式熟练构造分组报表 熟练构造Chart图形报表实现个人档案的PDF输出 数据填充 我们介绍了如何使用JasperReport来生成简单的文本报表&#xff0c;正式企业开发中动态数据展示也是报表中最重要的一 环&#xff0c;接下来我们共同研究的就是填…

FastCorrect:语音识别快速纠错模型丨RTC Dev Meetup

前言 「语音处理」是实时互动领域中非常重要的一个场景&#xff0c;在声网发起的「RTC Dev Meetup丨语音处理在实时互动领域的技术实践和应用」活动中&#xff0c;来自百度、寰宇科技和依图的技术专家&#xff0c;围绕该话题进行了相关分享。 本文基于微软亚洲研究院主管研究…

chatgpt赋能python:Python应用图标的SEO优化策略

Python应用图标的SEO优化策略 作为一门跨平台解释型编程语言&#xff0c;Python已经成为越来越多企业和开发者的首选语言之一。在Python应用的推广过程中&#xff0c;图标的设计和SEO优化也变得越来越重要。在本文中&#xff0c;我们将探讨Python应用图标的SEO优化策略&#x…

CCE集群切换OBS共享存储方案

目录 一、背景 二、创建PVC 三、同步nfs数据到OBS 四、变更无状态负载数据储存为OBS 五、卸载弹性文件服务SFS&#xff08;nfs&#xff09; 一、背景 生产环境CEE集群&#xff0c;每个K8s节点挂载同一个华为云弹性文件服务SFS(可以简单的理解为nfs)。无状态应用通过hostPath…

chatgpt赋能python:Python就业岗位:行业热门,前景广阔

Python 就业岗位&#xff1a;行业热门&#xff0c;前景广阔 作为其中一门最受欢迎的编程语言&#xff0c;Python 经常出现在各个行业的招聘需求中。无论是大企业、初创公司&#xff0c;还是政府机构和非营利组织&#xff0c;都需要 Python 专业人士来应对日益增长的数据和技术…

chatgpt赋能python:Python库使用指南

Python库使用指南 Python是一种高级编程语言&#xff0c;拥有丰富而强大的标准库和第三方库。在本文中&#xff0c;将介绍一些主要Python库的使用方法以及如何通过使用它们来提高SEO。 Requests库 Requests是一个流行的第三方库&#xff0c;用于HTTP请求和响应。可以使用它来…

【内网安全-隧道搭建】内网穿透_Spp上线(全双工通信)

目录 Spp&#xff08;特殊协议上线&#xff09; 1、简述&#xff1a; 2、用法&#xff1a; 1、准备 2、服务器 3、客户机 4、cs、msf Spp&#xff08;特殊协议上线&#xff09; 1、简述&#xff1a; 1&#xff09;支持的协议&#xff1a;tcp、udp、rudp&#xff08;可靠…