java根据用户请求获取ip地址,并解析省市信息_使用java实现根据ip地址查到具体地址-程序员宅基地

技术标签: java基础  java  ip  

1.选型

1.1 实现方式

Java可以实现IP地址解析和省市区信息查询,但是需要借助一些外部数据源或数据库来实现。常用的方法有以下几种:

1.1.1 本地文件解析

可以通过下载最新的IP地址段数据文件,然后在程序中解析该文件来获取IP地址对应的省市区等信息。不过这种方法需要手动维护IP库文件,并且更新和查询速度可能较慢,不适合高并发或大规模的应用场景。

1.1.2 数据库查询

可以将IP地址段数据存储在数据库中,然后根据用户请求的IP地址来查询对应的省市区等信息。常用的数据库有MySQL、Oracle、SQL Server等。这种方法可以提高查询效率和精度,并支持更灵活的查询方式,但是需要考虑数据库的设计和优化问题。

1.1.3 第三方API代理

使用第三方IP查询API代理来实现纯Java的IP地址解析和省市区信息查询。比如通过调用百度地图API、高德地图API等第三方服务来获取IP地址对应的位置信息。这种方法可以免去自行搭建IP数据库的麻烦,同时也能保证查询结果的准确性和实时性,但需要考虑API使用频率和费用等问题。

1.2 常用ip定位库

1.2.1 Ip2region

Ip2region:Ip2region是一个基于Java的IP地址定位库,提供了快速而准确的IP查询服务。它将全球IP地址划分为多级区域,可以根据IP地址获取对应的省市区信息、运营商等详细信息。

1.2.2 GeoLite2

GeoLite2:一款免费的IP地址库,由MaxMind公司开发和维护,提供高精度的IP地址定位服务。可通过下载数据库文件或使用API来查询IP地址对应的位置信息。

1.2.3 IP2Location

IP2Location:一款商业化的IP地址库,提供全球范围内的IP地址定位服务,支持IPv4/IPv6地址解析。可通过订阅服务或购买数据库文件来使用。

1.2.4 ipapi

ipapi:一款云端IP地址查询API,提供高效和准确的IP地址定位服务。支持JSON/XML格式的返回数据,可根据用户需求选择不同的套餐和服务计划。

1.2.5 QQWry

QQWry:国内最广泛使用的IP地址库之一,提供了IP地址到省市区县、运营商等信息的映射。可通过下载最新版的dat文件或使用API来实现IP地址定位。

1.2.6 其他

国内还有很多其他的定位库,如淘宝、新浪、搜狐等ip库,有兴趣的朋友自己了解下。

1.3 选择

综合下面几种情况考虑最后选择了 Ip2region
1.数据来源和准确性:数据是否完整、数据覆盖率、精度和实效性等。
2.许可协议和商业使用:是否需要授权、是否可用于商业用途、是否收费等。
3.支持的语言和平台

2.pom.xml依赖

我自己使用的springboot项目,基础依赖就不列举了

<dependencies>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.4.2</version>
    </dependency>
    <dependency>
        <groupId>org.lionsoul</groupId>
        <artifactId>ip2region</artifactId>
        <version>2.7.0</version>
    </dependency>
   <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
</dependencies>

3.代码示例

实体类接收国家、省市等信息。

@Data
public class IpLocation implements Serializable {
    

    @ApiModelProperty("ip地址")
    private String ip;

    @ApiModelProperty("国家")
    private String country;

    @ApiModelProperty("省")
    private String province;

    @ApiModelProperty("省")
    private String city;

    @ApiModelProperty("服务商")
    private String isp;
}

工具类:

@Slf4j
//@UtilityClass
public class IpUtils {
    

    /**
     * 字符常量0
     */
    private static final String ZERO="0";
    /**
     * 本级ip
     */
    private static final String LOCALHOST="127.0.0.1";

    /**
     * 获取客户端的IP地址
     */
    public static String getIpAddress(HttpServletRequest request) {
    
        String 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 || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
    
            ipAddress = request.getRemoteAddr();
            if (LOCALHOST.equals(ipAddress)) {
    
                // 根据网卡取本机配置的IP
                InetAddress inet = null;
                try {
    
                    inet = InetAddress.getLocalHost();
                    ipAddress = inet.getHostAddress();
                } catch (UnknownHostException e) {
    
                    e.printStackTrace();
                }
            }
        }
        // 对于通过多个代理转发的情况,取第一个非unknown的IP地址。
        // 这里假设第一个IP为真实IP,后面的为代理IP。
        if (ipAddress != null && ipAddress.length() > 15) {
    
            if (ipAddress.indexOf(",") > 0) {
    
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

    /**
     * 根据iP获取归属地信息
     * @return
     */
    public static IpLocation getLocation(String ip) {
    
        IpLocation location = new IpLocation();
        location.setIp(ip);
        try (InputStream inputStream = IpUtils.class.getResourceAsStream("/ip2region.xdb");) {
    
            byte[] bytes = IoUtil.readBytes(inputStream);
            Searcher searcher = Searcher.newWithBuffer(bytes);
            String region = searcher.search(ip);
            if (StrUtil.isAllNotBlank(region)) {
    
                // xdb返回格式 国家|区域|省份|城市|ISP,
                // 只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0
                String[] result = region.split("\\|");
                location.setCountry(ZERO.equals(result[0])?StrUtil.EMPTY:result[0]);
                location.setProvince(ZERO.equals(result[2])?StrUtil.EMPTY:result[2]);
                location.setCity(ZERO.equals(result[3])?StrUtil.EMPTY:result[3]);
                location.setIsp(ZERO.equals(result[4])?StrUtil.EMPTY:result[4]);
            }
            searcher.close();
        } catch (Exception e) {
    
            log.error("ip地址解析异常,error:{}",e);
            return location;
        }
        return location;
    }
}

在官网地址,将data目录下的ip2region.xdb文件复制到resource下。
图片.png
在百度输入ip地址查询,可以查到自己本地公网地址,测试如下(这里为了方便,直接写在了工具类里):
图片.png
如果需要测试 IP 地址查询功能,可以尝试使用一些公共的 IP 地址,例如:

  • 8.8.8.8:谷歌公共 DNS 地址,位于美国。
  • 114.114.114.114:中国电信公共 DNS 地址,位于中国。
  • 1.1.1.1:Cloudflare 公共 DNS 地址,位于澳大利亚。
  • 208.67.222.222:OpenDNS 公共 DNS 地址,位于美国。
  • 176.103.130.130:AdGuard 公共 DNS 地址,位于荷兰。

图片.png

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43993310/article/details/130873256

智能推荐

Java中的native方法的使用_native修饰方法-程序员宅基地

文章浏览阅读7.9k次,点赞25次,收藏106次。1.关于native关键字想必读者已经了解过native关键字了。这里笔者就大致囊括一下,被native关键字修饰的方法叫做本地方法,本地方法和其它方法不一样,本地方法意味着和平台有关,因此使用了native的程序可移植性都不太高。另外native方法在JVM中运行时数据区也和其它方法不一样,它有专门的本地方法栈。native方法主要用于加载文件和动态链接库,由于Java语言无法访问操作系统底层信息(比如:底层硬件设备等),这时候就需要借助C语言来完成了。被native修饰的方法可以被C语言重写。2.使_native修饰方法

Thread类-程序员宅基地

文章浏览阅读1.3w次,点赞7次,收藏60次。 1 start方法  start()用来启动一个线程,当调用start方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。  2 run方法  run()方法是不需要用户来调用的,当通过start方法启动一个线程之后,当线程获得了CPU执行时间,便进入run方法体去执行具体的任务。注意,继承Thread类必须重写run方法,在run方法中定义具体要..._thread类

oracle数据落地到gp,使用ora2pg迁移oracle数据到greenplum-程序员宅基地

文章浏览阅读377次。安装ora2pg条件1、perl版本5.10以上2、安装DBD::Oracle3、安装DBI4、安装DBD::Pg一、安装相关软件支持1、安装DBI#下载https://metacpan.org/release/DBI上传到服务器并解压出来DBI-1.637.tar.gz[ root@bigdata01 ~]$ lltotal 592-rw-r--r-- 1 gpadmin gpadmin 596..._ora2pg greenplum

UVA 1411 Ants 二分图最佳完美匹配_给定一个二分图,该二分图有 nn 个黑点与 nn 个白点-程序员宅基地

文章浏览阅读370次。UVA 1411题意:有n个白点和n个黑点,要求用n条不相交的线段把他们连接起来,其中每条线段恰好连接一个白点和一个黑点。思路:连接两点a1和b1,如果还有其他的线段a2,b2相连与之相交,必有dist(a1,b1)+dist(a2,b2)大于dist(a1,b2)+dist(a2,b1),原因是两条相交线段构成了几个三角形,三角形性质有两边之和必大于第三边,所以,如果每条线段都没有与之相..._给定一个二分图,该二分图有 nn 个黑点与 nn 个白点

TensorFlow学习2:使用自己的数据批量训练网络_tensorflow 实现简单的批处理训练例子-程序员宅基地

文章浏览阅读1k次。使用自己的数据训练网络时,需要用到两个函数:tf.train.slice_input_producer、tf.train.batch和两个类tf.train.Coordinator和tf.QueueRunner。参考博客:tensorflow中 tf.train.slice_input_producer 和 tf.train.batch 函数和tensorflow中协调器 tf.train.Co..._tensorflow 实现简单的批处理训练例子

通用检测模型合集-程序员宅基地

文章浏览阅读368次,点赞8次,收藏10次。其中,基于注意力的伪标记方案是主要来获取候选未知查询的,从中间特征的注意力图上求取各个查询的平均分数(比如a-e),然后再用top-k来分配是不是物体,此阶段只区分unknown和no-objects两类,上图中a,b,c是unknown类别,d,e是非目标类别。论文的开放世界目标检测模型使用基于能量的分类头和对未知类别敏感的RPN来识别潜在的未知对象,此外,在特征空间中进行对比学习,以学习有区分性的聚类,并可以灵活地以连续的方式添加新的类别,而不会遗忘先前的类别。然后,查询的目标分数用于识别伪未知对象。_检测模型

随便推点

JavaWeb-通过表格显示数据库的信息(jsp+mysql)_javaweb数据库数据显示在表单-程序员宅基地

文章浏览阅读1.2w次,点赞14次,收藏113次。login.jsp&lt;%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%&gt;&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;&lt;html&gt;&lt;head&gt_javaweb数据库数据显示在表单

异常账号检测汇总_异常登录数据集-程序员宅基地

文章浏览阅读2.5k次。账户异常检测_异常登录数据集

windows上编译,使用libtorrent_windows libtorrent怎么用-程序员宅基地

文章浏览阅读3.2k次,点赞2次,收藏4次。花了几天的时间,查找了很多资料,基本上没有找到能够编译成功教程特留下此篇博客已做参考:windows编译libtorrent需要依赖于OpenSSL库,和boost库,建议直接下载一. 编译OpenSSL的库 编译OpenSSL网上教程一大堆,自己去找,我这里不介绍 编译好的OpenSSL库下载地址二. 编译boost库 参考地址:https..._windows libtorrent怎么用

第37讲:MySQL索引结构之B-Tree和B+Tree数据结构的概念_- mysql数据库中的b+树,b-树结构-程序员宅基地

文章浏览阅读3.2k次,点赞26次,收藏16次。现在的节点中有四个数据,再插入一个22之后,按照从小到大的顺序,22会放在50的前面,这样一来节点中就有5个key了,违背了5阶的概念,此时就会取中间元素,向上分裂,中间元素也就是中间数,60就是中间元素,60就向上分裂,形成一个新的节点,剩下的4个key也会分裂成两个子节点。插入22这个数据,观察效果,就如刚刚说的,第五个key进入节点后,不满足5阶的概念,中间元素向上分裂,60是中间元素,直接向上分裂,形成一个新的节点,其余的4个key成为新节点中的子节点。_- mysql数据库中的b+树,b-树结构

RPA教学:Python“奇怪的“&“特殊的“数字字符串处理_影刀rpa处理特殊字符串-程序员宅基地

文章浏览阅读422次。了解RPA:www.i-search.com.cn学习RPAhttps://support.i-search.com.cn/下载RPA:https://www.i-search.com.cn/?from=csdn众所周知,在某些特殊情况下,有些人会使用各种奇奇怪怪的符号来表示数字。例如有些人写自己的 QQ 号,是这样写的:加暁眉扣:玖壹五捌⑦二Ⅲ9再不久前我是这样创建一个字典并写一个转换方法来对其进行处理:{‘一’: 1,‘壹’: 1, ‘①’: 1,‘二’: 2, ‘三’: 3, …}_影刀rpa处理特殊字符串

element-ui使用axios获取并下载流文件到本地_elementui下载文件到本地-程序员宅基地

文章浏览阅读1k次。首先使用axios发送一个GET请求,并将其响应类型设置为“stream”。这将使axios返回一个包含可读流的响应对象。我们然后创建一个可写流,并将响应数据流(pipe)到可写流中。最后,我们返回一个Promise,以便在下载完成时进行通知。当Promise被resolve时,文件将下载到本地磁盘,并且可以使用相应的路径访问。如果下载过程中发生错误,Promise将被reject,并且在控制台上将打印出错误消息。_elementui下载文件到本地

推荐文章

热门文章

相关标签