Java根据ip地址获取归属地

news2024/10/5 12:47:59

最近,各大平台都新增了评论区显示发言者ip归属地的功能,例如哔哩哔哩,微博,知乎等等。

下面,我就来讲讲,Java 中是如何获取 IP 属地的,主要分为以下几步

  • 通过 HttpServletRequest 对象,获取用户的 IP 地址
  • 通过 IP 地址,获取对应的省份、城市

首先需要写一个 IP 获取的工具类,因为每一次用户的 Request 请求,都会携带上请求的 IP 地址放到请求头中。

public class IpUtils {

    /**
     * 获取ip地址
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request){
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("X-Forwarded-For");
            if (ipAddress != null && ipAddress.length() != 0 && !"unknown".equalsIgnoreCase(ipAddress)) {
                // 多次反向代理后会有多个ip值,第一个ip才是真实ip
                if (ipAddress.indexOf(",") != -1) {
                    ipAddress = ipAddress.split(",")[0];
                }
            }
            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 || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
            }
        }catch (Exception e) {
            log.error("IPUtils ERROR ",e);
        }
        return ipAddress;
    }

对这里出现的几个名词解释一下:

  • X-Forwarded-For:一个 HTTP 扩展头部,主要是为了让 Web 服务器获取访问用户的真实 IP 地址。每个 IP 地址,每个值通过逗号+空格分开,最左边是最原始客户端的 IP 地址,中间如果有多层代理,每⼀层代理会将连接它的客户端 IP 追加在 X-Forwarded-For 右边。

  • Proxy-Client-IP:这个一般是经过 Apache http 服务器的请求才会有,用 Apache http 做代理时一般会加上 Proxy-Client-IP 请求头

  • WL-Proxy-Client-IP:也是通过 Apache http 服务器,在 weblogic 插件加上的头。

  • X-Real-IP:一般只记录真实发出请求的客户端IP

  • HTTP_CLIENT_IP:代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。

这里,要着重介绍一下Ip2region项目。

github地址:github.com/lionsoul201…

 

一个准确率 99.9% 的离线 IP 地址定位库,0.0x 毫秒级查询,ip2region.db 数据库只有数MB,提供了 java,php,c,python,nodejs,golang,c# 等查询绑定和Binary,B树,内存三种查询算法。

内置的三种查询算法

全部的查询客户端单次查询都在 0.x 毫秒级别,内置了三种查询算法

  • memory 算法:整个数据库全部载入内存,单次查询都在0.1x毫秒内,C语言的客户端单次查询在0.00x毫秒级别。

  • binary 算法:基于二分查找,基于ip2region.db文件,不需要载入内存,单次查询在0.x毫秒级别。

  • b-tree 算法:基于btree算法,基于ip2region.db文件,不需要载入内存,单词查询在0.x毫秒级别,比binary算法更快。

使用方法

1、引入ip2region依赖

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

2、下载仓库中的ip2region.db 文件,放到工程resources目录下

3、编写方法加载ip2region文件,对用户ip地址进行转换。

/**
 * 获取ip属地
 * @param ip
 * @return
 * @throws Exception
 */
public static String getCityInfo(String ip) throws Exception {
    //获得文件流时,因为读取的文件是在打好jar文件里面,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources("ip2region.db");
    Resource resource = resources[0];
    InputStream is = resource.getInputStream();
    File target = new File("ip2region.db");
    FileUtils.copyInputStreamToFile(is, target);
    is.close();
    if (StringUtils.isEmpty(String.valueOf(target))) {
        log.error("Error: Invalid ip2region.db file");
        return null;
    }
    DbConfig config = new DbConfig();
    DbSearcher searcher = new DbSearcher(config, String.valueOf(target));
    //查询算法
    //B-tree, B树搜索(更快)
    int algorithm = DbSearcher.BTREE_ALGORITHM;
    try {
        //define the method
        Method method;
        method = searcher.getClass().getMethod("btreeSearch", String.class);
        DataBlock dataBlock;
        if (!Util.isIpAddress(ip)) {
            log.error("Error: Invalid ip address");
        }
        dataBlock = (DataBlock) method.invoke(searcher, ip);
        String ipInfo = dataBlock.getRegion();
        if (!StringUtils.isEmpty(ipInfo)) {
            ipInfo = ipInfo.replace("|0", "");
            ipInfo = ipInfo.replace("0|", "");
        }
        return ipInfo;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

4、由于 ip 属地在国内的话,只会展示省份,而国外的话,只会展示国家。所以我们还需要对这个方法进行一下封装,得到获取 IP 属地的信息。

public static String getIpPossession(String ip) throws Exception {
    String cityInfo = IpUtils.getCityInfo(ip);
    if (!StringUtils.isEmpty(cityInfo)) {
        cityInfo = cityInfo.replace("|", " ");
        String[] cityList = cityInfo.split(" ");
        if (cityList.length > 0) {
            // 国内的显示到具体的省
            if ("中国".equals(cityList[0])) {
                if (cityList.length > 1) {
                    return cityList[1];
                }
            }
            // 国外显示到国家
            return cityList[0];
        }
    }
    return "未知";
}

5、编写测试类。

public static void main(String[] args) throws Exception {

    //国内ip
    String ip1 = "220.248.12.158";

    String cityInfo1 = IpUtils.getCityInfo(ip1);
    System.out.println(cityInfo1);
    String address1 = IpUtils.getIpPossession(ip1);
    System.out.println(address1);

    //国外ip
    String ip2 = "67.220.90.13";
    String cityInfo2 = IpUtils.getCityInfo(ip2);
    System.out.println(cityInfo2);
    String address2 = IpUtils.getIpPossession(ip2);
    System.out.println(address2);
}

6、测试结果

最后,附上项目用到的全部依赖,想了解的小伙伴可以学习一下!

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
</dependency>
<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>1.7.2</version>
</dependency>

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.11.0</version>
</dependency>

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

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

相关文章

JVM监控及诊断工具-GUI

1. 工具概述 使用上一章命令行工具或组合能帮您获取目标Java应用性能相关的基础信息&#xff0c;但它们存在下列局限: 1)无法获取方法级别的分析数据&#xff0c;如方法间的调用关系、各方法的调用次数和调用时间 等&#xff08;这对定位应用性能瓶颈至关重要&#xff09;。 2…

【MybatisPlus】最全面的MybatisPlus通关教程

前言 本文为最全面的MybatisPlus通关教程相关介绍&#xff0c;下边将对MyBatisPlus概述&#xff0c;MyBatisPlus快速入门&#xff0c;CRUD扩展&#xff08;包括&#xff1a;插入操作、主键生成策略、更新操作&#xff0c;自动填充&#xff0c;乐观锁&#xff0c;查询操作&#…

我学python的那段日子(四)选择结构和循环结构

1.选择结构 总所周知&#xff0c;Java里面也有选择结构&#xff0c;分别是if单分支选择结构、if-else结构多重if结构和switch结构&#xff0c;同样的&#xff0c;Python里也有选择结构&#xff0c;分别是是if单分支选择结构、if-else结构多重if结构。 1.1 if选择结果 ​ if选…

Servlet生命周期和线程安全

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;JAVA开发者…

CANoe-是如何对ECU和网络进行测试的

CANoe工具是汽车仿真测试开发中使用最广泛的工具 Test Module/Test Unit 除了仿真模块和分析模块,CANoe还引入了另一个组件进行测试:Test Module(测试模块)和Test Unit(测试单元) test module调用的是capl脚本、.net脚本或xml文件,而test unit用的是vTESTstudio插件 实…

12.18

一.加强练习promise 1.fs模块 const fs require(fs) const p new Promise((resolve,reject) > {fs.readFile(./resource/context.txt, (err,data) > {if (err) reject(err)resolve(data)}) }) p.then((value) > {console.log(value.toString()) }, (reason) > …

前端炫酷特效合集

我们经常在抖音上看到一些前端很酷的特效&#xff0c;诸如&#xff1a;快叫你学编程的朋友给你写一个圣诞树&#xff0c;看着是不是很酷炫呢&#xff1f;其实只要有源码&#xff0c;你也可以拥有哦&#xff01; 跟大家分享多款前端特效源码&#xff0c;需要的朋友可以去在这里…

Java : 多态,包装类的面试题:

Java &#xff1a; 多态&#xff0c;包装类的面试题&#xff1a; 每博一文案 有人说&#xff1a;小孩子才会仰天大哭&#xff0c;成年人的世界早就调成了静音模式&#xff0c;连崩溃也很懂事。 一路走来&#xff0c;我们一边受伤&#xff0c;也一边变得更坚强&#xff0c;慢慢…

数据库原理及MySQL应用 | 日志管理

数据库系统管理维护阶段需要通过日志对数据库的性能进行监督、分析和改进。 日志是数据库系统的重要组成部分&#xff0c;记录了数据库的运行状态、数据的变更历史、错误信息及用户操作等信息。在日常管理中&#xff0c;数据库管理员可通过日志监控数据库的运行状态、优化数据库…

国内外文献镜像网站

一、常用的国内外文献镜像网站 维普网&#xff1a;http://lib.cqvip.com/ idata&#xff1a;https://www.cn-ki.net/ 独秀&#xff1a;https://www.duxiu.com/ 中国知网&#xff1a;https://www.cnki.net/ 龙源期刊网&#xff1a;http://www.qikan.com.cn/ 万方数据&#xff1…

计算机毕业设计HTML+CSS+JavaScript仿大型购物商城(1页)

常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他等网页设计题目, A…

毕业设计 单片机GPS定位位置记录系统 - 物联网 嵌入式 stm32

文章目录0 前言1 简介2 主要器件3 实现效果4 硬件设计概述硬件模块的连接**AB32VG1主控MCU**5 软件说明6 部分核心代码7 最后0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到毕业答辩…

基于asp.net人力资源管理系统-计算机毕业设计

基于asp.net的人力资源管理的内容和人事管理日常管理所遇到的问题&#xff0c;整个系统可以分为下面几个子模块&#xff0c;分别为员工档案信息管理、工资信息管理、考勤信息管理、消息信息管理、账号信息管理等几个大的功能模块,开发环境:Visual studio,sqlserver数据库.资料有…

非零基础自学Golang 第9章 结构体 9.4 初始化结构体

非零基础自学Golang 文章目录非零基础自学Golang第9章 结构体9.4 初始化结构体9.4.1 键值对格式初始化9.4.2 列表格式初始化第9章 结构体 9.4 初始化结构体 上一小节我们讲解了在结构体实例化后&#xff0c;再使用“.”的方式对成员变量进行赋值。另外&#xff0c;我们还可以…

Junit5 架构、新特性及基本使用(常用注解与套件执行)

什么是 Junit5&#xff0c;在 Junit5 的官方介绍文档中这写到&#xff1a; Junit5 由JUnit Platform JUnit Jupiter JUnit Vintage3部分构成&#xff0c;借用 IBM Developer 的一张图来说明 JUnit 5 的架构&#xff1a; JUnit Platform: JUnit Jupiter: JUnit Vintage: 嵌套单…

Spring Cloud 总结 - 调用远程服务的三种方式及原理分析

一个简单的微服务架构图 本文设计的 Spring Cloud 版本以及用到的 Spring Cloud 组件 Spring Cloud Hoxton.SR5eurekafeignribbon 后面的内容都将围绕上面的图来分析. 调用远程服务的三种方式 在 Spring Cloud 服务架构中, 一个服务可能部署多个实例, 通常情况下, 这个时候…

好玩的网站安利

好玩的网站安利 1、EGOUZ https://www.egouz.com/ 授人以鱼不如授人以渔&#xff0c;先给大家分享两个可以找国外优质网站的地方。EGOUZ是一个高质量的导航站&#xff0c;内容主要是外国网站&#xff0c;并且做了很详细的分类&#xff0c;网站资源非常丰富。 EGOUZ按照国家分…

50450-80-1,Ala-Ala-Ala-对硝基苯胺

AAA-pNA, chromogenic substrate for porcine pancreatic elastase and for astacin, a crayfish zinc-endopeptidase.3a - pna&#xff0c;猪胰腺弹性酶和阿斯塔星的显色底物&#xff0c;阿斯塔星是一种小龙虾锌内肽酶。 编号: 163840中文名称: 三肽Pancreatic elastase subst…

1573_AURIX_TC275_SCU中的急停功能以及overlay

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 急停功能是不需要软件进行干预的&#xff0c;至少&#xff0c;这个事件的动作触发是不需要软件进行干预的。急停事件的触发因素&#xff1a;外部的输入事件、SMU的警报信息。外部的输入事件…

概率论 ‖ Machine Learning必备知识

概率论&#xff01;Machine Learning必备知识 文章目录概率论&#xff01;Machine Learning必备知识1 什么是概率1.1 最简单的例子1.2 概率论与数理统计的关系2 大数定律和中心极限定理2.1 大数定律是什么&#xff1f;2.2 代码直观理解大数定律2.3 中心极限定理2.4 大数定律和中…