使用强大的离线IP地址定位库ip2region获取城市信息

x33g5p2x  于2022-02-28 转载在 其他  
字(3.2k)|赞(0)|评价(0)|浏览(471)

一、简介

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

二、ip2region的使用

1、引入依赖

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

2、下载ip2region.db

这个可以在gitee仓库(https://gitee.com/lionsoul/ip2region)下载,在项目的data目录下。

3、IpUtils工具类

我封装了一个IpUtils工具类,主要有两个方法,一个是去获取请求中的真实客户端ip,一个是通过ip获取城市信息。

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * IP城市定位
 *
 * @author
 * @Date 2021/1/1
 */
@Slf4j
public class IPUtils {
    private static final String DB_PATH = "C:\\Users\\yanyunfan\\Downloads\\ip2region.db";
    private static final String DEFAULT_CITY_NAME = "未知";

    /**
     * 获取城市信息
     *
     * @param ip        ip
     * @param algorithm 算法
     * @return
     */
    public static String getIpAddress(String ip, int algorithm) {
        if (Util.isIpAddress(ip)) {
            return DEFAULT_CITY_NAME;
        } else if ("127.0.0.1".equals(ip) || StringUtils.startsWith(ip, "192.168")) {
            return "内网IP";
        }

        // 查询算法B-tree, Binary, Memory
        DbSearcher searcher = null;
        try {
            DbConfig config = new DbConfig();
            searcher = new DbSearcher(config, DB_PATH);

            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:
                default:
                    method = searcher.getClass().getMethod("memorySearch", String.class);
                    break;
            }

            DataBlock dataBlock = (DataBlock) method.invoke(searcher, ip);
            List<String> list = Arrays.asList(dataBlock.getRegion().split("\\|")).stream().filter(s -> !"0".equals(s)).collect(Collectors.toList());
            String ipAddress = StringUtils.join(list, ",");
            return ipAddress;
        } catch (Exception e) {
            log.error("获取城市信息失败:", e);
        } finally {
            try {
                searcher.close();
            } catch (IOException e) {
            }
        }
        return DEFAULT_CITY_NAME;
    }

    /**
     * 获取客户端ip
     *
     * @param request 请求
     * @return
     */
    public static String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        } else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        } else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        } else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        } else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static void main(String[] args) {
        String ip = "1.80.0.0";
        String cityIpString = getIpAddress(ip, 2);
        System.out.println(cityIpString);
    }
}

控制台输出:

中国,陕西省,西安市,电信

相关文章