【Java】根据IP地址获取省市

简介: 【Java】根据IP地址获取省市

方案一

最近要做一个埋点的功能,需求里要求记录用户登录的IP和地点,打算利用ip2region.db实现

首先下载ip2region.db

地址:下载地址

ip2region是一套准确率99.9%的ip地址定位库,0.0x毫秒级查询,数据库文件大小只有1.6M,提供了java, php, c, python,nodejs,golang查询绑定和Binary,B树,内存三种查询算法

导入依赖

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

工具类.

package com.croot.rims.utils;

import com.google.common.io.Resources;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;

public class IPUtil {

    /**
     * 获取IP地址
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if ("0:0:0:0:0:0:0:1".equals(ip)) {
            ip = "127.0.0.1";
        }
        if (ip.split(",").length > 1) {
            ip = ip.split(",")[0];
        }
        return ip;
    }

    /**
     * 根据IP地址获取城市
     * @param ip
     * @return
     */
    public static String getCityInfo(String ip) throws IOException {
        URL url = IPUtil.class.getResource("/ip2region.db");
        File file;
        file = new File("/app/project/croot_rims/package/webserver/ip2region.db");
        if (!file.exists()) {
            System.out.println("Error: Invalid ip2region.db file, filePath:" + file.getPath());
            return null;
        }
        //查询算法
        int algorithm = DbSearcher.BTREE_ALGORITHM; //B-tree
        //DbSearcher.BINARY_ALGORITHM //Binary
        //DbSearcher.MEMORY_ALGORITYM //Memory
        try {
            DbConfig config = new DbConfig();
            DbSearcher searcher = new DbSearcher(config, file.getPath());
            Method method;
            switch ( algorithm )
            {
                case DbSearcher.BTREE_ALGORITHM:
                    method = searcher.getClass().getMethod("btreeSearch", String.class);
                    break;
                case DbSearcher.BINARY_ALGORITHM:
                    method = searcher.getClass().getMethod("binarySearch", String.class);
                    break;
                case DbSearcher.MEMORY_ALGORITYM:
                    method = searcher.getClass().getMethod("memorySearch", String.class);
                    break;
                default:
                    return null;
            }
            DataBlock dataBlock;
            if (!Util.isIpAddress(ip)) {
                System.out.println("Error: Invalid ip address");
                return null;
            }
            dataBlock  = (DataBlock) method.invoke(searcher, ip);
            return dataBlock.getRegion();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

具体使用

String detail = IpUtils.getCityInfo("113.105.172.33");

具体效果

中国|华南|广东省|东莞市|电信

方案二

在Java中,我们可以使用第三方库,例如"GeoIP"来获取IP地址所对应的地理位置信息。这个库是基于MaxMind的GeoLite数据库,它包含了大量的IP地址和相应的地理位置信息。

首先,你需要下载GeoLite数据库(这是一个.dat文件),然后将其放在你的项目的某个位置。接下来,你可以编写一个函数来查询这个数据库并获取IP地址的地理位置信息。

以下是一个简单的示例:

import com.maxmind.geoip2.DatabaseReader;  
import com.maxmind.geoip2.exception.GeoIp2Exception;  
import com.maxmind.geoip2.model.CityResponse;  
import com.maxmind.geoip2.record.City;  
  
import java.io.File;  
import java.io.IOException;  
import java.net.InetAddress;  
  
public class GeoIPTest {  
    public static void main(String[] args) throws IOException, GeoIp2Exception {  
        String ipAddress = "你的IP地址";  // 替换成你要查询的IP地址  
        File database = new File("你的数据库文件路径"); // 替换成你的GeoLite数据库文件路径  
        DatabaseReader dbReader = new DatabaseReader.Builder(database).build();  
        InetAddress ip = InetAddress.getByName(ipAddress);  
        CityResponse response = dbReader.city(ip);  
        City city = response.getCity();  
        System.out.println(city.getName());  // 输出城市名  
    }  
}

注意:这个例子只能获取到城市级别的信息,如果你需要更详细的信息(比如具体的经纬度),你可以查看CityResponse对象的其他方法。

最后,别忘了将这个库添加到你的项目依赖中。如果你使用的是Maven,你可以在你的pom.xml文件中添加以下依赖:

<dependency>  
    <groupId>com.maxmind.geoip2</groupId>  
    <artifactId>geoip2</artifactId>  
    <version>2.12.0</version>  <!-- 请检查最新版本 -->  
</dependency>

以上方法即可根据IP地址获取省市信息

总结

除了使用GeoIP库之外,还有其他一些方案可以用于根据IP地址获取省市信息。以下是其中几个方案:

使用第三方API服务:有一些第三方服务提供了根据IP地址获取地理位置信息的功能,例如IP2Location和GeoIP2。这些服务通常提供了简单的API,你可以在Java中使用HTTP请求调用这些API,然后获取相应的地理位置信息。

自行搭建数据库:除了使用第三方数据库之外,你还可以自行搭建数据库来存储IP地址和相应的地理位置信息。你可以使用公开的IP地址数据源,例如IP2Location和GeoIP2,将其下载下来并存储在你的数据库中。然后,你可以编写Java程序来查询这个数据库并获取IP地址的地理位置信息。

这些方案各有优缺点。使用第三方API服务可以省去自己搭建数据库和维护的麻烦,但需要支付一定的费用。自行搭建数据库可以节省费用,但需要花费时间和精力去搭建和维护。在选择方案时,你需要根据自己的需求和实际情况进行评估和选择。

目录
相关文章
Java 如何根据域名查询对应的ip地址
Java 如何根据域名查询对应的ip地址
600 3
|
6月前
|
存储
JavaWeb如何获取当前访问IP
JavaWeb如何获取当前访问IP
140 0
|
5月前
|
网络协议 安全 Java
Java网络编程入门涉及TCP/IP协议理解与Socket通信。
【6月更文挑战第21天】Java网络编程入门涉及TCP/IP协议理解与Socket通信。TCP/IP协议包括应用层、传输层、网络层和数据链路层。使用Java的`ServerSocket`和`Socket`类,服务器监听端口,接受客户端连接,而客户端连接指定服务器并交换数据。基础示例展示如何创建服务器和发送消息。进阶可涉及多线程、NIO和安全传输。学习这些基础知识能助你构建网络应用。
49 1
|
6月前
|
网络协议 Java
Java的Socket编程:TCP/IP与UDP深入探索
Java的Socket编程:TCP/IP与UDP深入探索
101 0
|
5月前
|
网络协议 Java 程序员
TCP/IP协议栈是网络通信基础,Java的`java.net`包提供工具,使开发者能利用TCP/IP创建网络应用
【6月更文挑战第23天】 **TCP/IP协议栈是网络通信基础,它包含应用层(HTTP, FTP等)、传输层(TCP, UDP)、网络层(IP)、数据链路层(帧, MAC地址)和物理层(硬件信号)。Java的`java.net`包提供工具,使开发者能利用TCP/IP创建网络应用,如Socket和ServerSocket用于客户端和服务器通信。**
54 3
|
4月前
|
Java Redis 数据安全/隐私保护
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
Redis13的Java客户端-Jedis快速入门,建立连接的写法,ip地址,设置密码密码,选择库的写法
|
5月前
|
Java Apache Maven
蓝易云 - java判断ip是否为指定网段
在这个例子中,我们首先创建了一个 `SubnetUtils`对象,它表示一个子网。然后,我们使用 `isInRange`方法来检查指定的IP地址是否在这个子网内。如果IP地址在子网内,`isInRange`方法将返回 `true`,否则返回 `false`。
107 3
|
5月前
|
数据采集 Java 数据安全/隐私保护
使用Java进行网络采集:代理IP与参数传递详解
Java参数传递是按值传递,包括对象引用的值。当传递对象时,方法内部修改对象内容会影响原始对象,但不能改变原始引用。示例展示了如何在爬虫代理中使用此机制,通过`ProxySettings`类传递代理信息,方法内可访问但不能更改原始对象。理解这一机制对编写高效无错的Java代码至关重要。
使用Java进行网络采集:代理IP与参数传递详解
|
6月前
|
存储 Java
Java动态转发代理IP的实现方法
Java动态转发代理IP的实现方法
283 11
|
6月前
|
安全 Java API
java借助代理ip,解决访问api频繁导致ip被禁的问题
java借助代理ip,解决访问api频繁导致ip被禁的问题
114 2