SpringBoot集成ip2region2.X

离线IP地址定位库主要用于内网或想减少对外访问http带来的资源消耗。本博客使用的是ip2region + 在线获取。

ip2region总体分为两个大版本:

1.x:提供三种算法,其中内存查询速度在0.1x毫秒级别,离线库文件ip2region.db

2.x:同样提供三种算法,其中内存查询速度在微秒级别,离线库文件ip2region.xdb

本篇文章将以2.X版本进行演示。

基本配置

1、离线库下载:

github:https://github.com/lionsoul2014/ip2region/tree/master/data

将文件下载完成后,放到项目的resource目录下新建的ip2region目录中:

2、POM文件:

<!-- 离线IP地址定位库 -->
<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>2.6.5</version>
</dependency>

<!-- 识别xdb文件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <encoding>UTF-8</encoding>
        <nonFilteredFileExtensions>
            <nonFilteredFileExtension>xdb</nonFilteredFileExtension>
        </nonFilteredFileExtensions>
    </configuration>
</plugin>

AddressUtils

import com.alibaba.fastjson.JSONObject;
import com.xffjs.common.utils.http.HttpUtils;
import com.xffjs.framework.config.SystemConfig;
import org.apache.commons.io.FileUtils;
import org.apache.shiro.io.ResourceUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Method;

/**
 * @className: AddressUtils
 * @description: ip地址获取位置工具类
 * @author: xiaofei
 * @create: 2021年04月11日
 */
public class AddressUtils {

    private final static Logger LOGGER = LoggerFactory.getLogger(AddressUtils.class);

    /**
     *  可参考下面文章进行修改: https://blog.xffjs.com/f/article/93.html
     */
    public static final String IP_URL4 = "";

    /**
     * 根据ip获取位置
     *
     * @param ip
     * @return 国家|区域|省份|城市|ISP_
     */
    public static String getRealAddressByIp(String ip) {
        long startTime = System.currentTimeMillis();
        String address = "";
        // 内网不查询
        if (IpUtils.internalIp(ip)) {
            return "内网IP";
        }
        address = getRegion(ip);
        if (StringUtils.isEmpty(address)) {
            if (SystemConfig.isAddressEnabled()) {
                String rspStr = HttpUtils.sendPost(IP_URL4, "ip=" + ip);
                if (StringUtils.isEmpty(rspStr)) {
                    LOGGER.error("获取地理位置异常 {}", ip);
                    return address;
                }
                JSONObject obj = JSONObject.parseObject(rspStr);
                String country = obj.getString("country");
                String region = obj.getString("province");
                String city = obj.getString("city");
                String isp = obj.getString("isp");
                if (address.equals(region) && address.equals(city)) {
                    return obj.getString("country") + obj.getString("isp") + "流量";
                }
                address = country + "|" + "999|" + region + "|" + city + "|" + isp;
            }
        }
        long endTime = System.currentTimeMillis();
        LOGGER.debug("获取ip位置耗时:[{}] ", endTime - startTime);
        return address;
    }


    //********************************* 根据ip离线查询地址Star ***********************************************************
    protected static Searcher searcher;

    static {
        InputStream resourceAsStream = AddressUtils.class.getClassLoader().getResourceAsStream("ip2region/ip2region.xdb");
        if (resourceAsStream != null) {
            byte[] cBuff;
            try {
                cBuff = FileCopyUtils.copyToByteArray(resourceAsStream);
                searcher = Searcher.newWithBuffer(cBuff);
            } catch (IOException e) {
                LOGGER.error("AddressUtils-error:{}", e);
            } finally {
                try {
                    resourceAsStream.close();
                } catch (Exception e) {
                    LOGGER.error("AddressUtils-error:{}", e);
                }
            }
        }
    }

    public static Searcher getSearch() {
        return searcher;
    }

    /**
     * 离线根据ip获取位置--2.X
     *
     * @param ip
     * @return 国家|区域|省份|城市|ISP_
     */
    public static String getRegion(String ip) {
        long ipLong = ipToLong(ip);
        try {
            String search = searcher.search(ipLong);
            if (StringUtils.isNotEmpty(search)) {
                return search;
            }
        } catch (Exception e) {
            LOGGER.error("AddressUtils-error:{}", e);
        }
        return StringUtils.EMPTY;
    }

    //********************************* 根据ip离线查询地址End ***********************************************************

    /**
     * ip转long
     *
     * @param ip
     * @return long
     */
    public static long ipToLong(String ip) {
        String[] split = ip.split("\\.");
        long i1 = 0L;
        i1 += (long) Integer.parseInt(split[0]) << 24;
        i1 += (long) Integer.parseInt(split[1]) << 16;
        i1 += (long) Integer.parseInt(split[2]) << 8;
        return i1 + Integer.parseInt(split[3]);
    }
}