数据分析不可避免经常遇到IP地址解析,在免费开源的前提下编写了一个IP归属查询工具类

发现IP开源库GEOIP现在只能查询到省级,于是又从csdn上面找到一个经纬信息对应城市的sql数据,于是便能免费查询到市级甚至市级一下的IP归属信息了 首先是官方依赖:


       <!--mmdb-->
        <dependency>
            <groupId>com.maxmind.geoip2</groupId>
            <artifactId>geoip2</artifactId>
            <version>2.10.0</version>
        </dependency>

然后上码:

/**
 * IPHelper
 *
 * @author nan
 * @date 2018/08/29
 */
@Slf4j
public class IpAddressHelper implements Closeable {

    private File databaseFile;
    private Reader reader ;
    private Db Db;
    private static final int RANGE = 5;
    private static final String UN_KNOWN  = "";
    private static final int COUNTRY_LENGTH = 4;
    private WeakCache<String, Map> weakCache = CacheUtil.newWeakCache(-1);

    public IpAddressHelper(Db Db){
        try {
            this.Db = Db;
            String path = "mmdb/GeoLite2-City.mmdb";
            if (!FileUtil.file(path).exists()){
                InputStream resourceAsStream = IpAddressHelper.class.getClassLoader().getResourceAsStream(path);
                File file = ResourceUtils.getFile(path);
                FileOutputStream tempStream = new FileOutputStream(FileUtil.touch(file));
                IoUtil.copy(resourceAsStream, tempStream);
                tempStream.close();
                reader = new Reader(FileUtil.touch(file));
            }else {
                reader = new Reader(FileUtil.file(path));
            }
        } catch (FileNotFoundException e) {
            log.error("Not Found File classpath:GeoLite2-City.mmdb",e);
            throw new RuntimeException(e);
        } catch (IOException e) {
            log.error("Error Reader databaseFile:GeoLite2-City.mmdb",e);
            throw new RuntimeException(e);
        }
    }

    public Map getRegionOrWithCache(final String ip){
        Map result = weakCache.get(ip);
        if (null != result ){
            return result;
        }else {
            result = getRegion(ip);
            weakCache.put(ip,result);
            return result;
        }
    }
    public Map getRegion(final String ip){

        Map<String, Object> result = new HashMap<>( 3 );
        try {
            InetAddress address = InetAddress.getByName(ip);
            JsonNode response = reader.get(address);
            if (!Objects.isNull( response )) {
                String latitude = response.get("location").get("latitude").toString();
                String longitude = response.get("location").get("longitude").toString();
                String country = response.get("registered_country").get("names").get("zh-CN").toString();
                if (StrUtil.isNotBlank( country ) && country.length()>= COUNTRY_LENGTH) {
                    country = country.substring( 1, country.length()-1 );
                }

                List<Entity> queryResult = Db.query("select * from dc_area_position " +
                        "   where sqrt(  \n" +
                        "         (  \n" +
                        "          (("+longitude+"-longitude)*PI()*12656*cos((("+latitude+"+latitude)/2)*PI()/180)/180)  \n" +
                        "          *  \n" +
                        "          (("+longitude+"-longitude)*PI()*12656*cos ((("+latitude+"+latitude)/2)*PI()/180)/180)  \n" +
                        "         )  \n" +
                        "         +  \n" +
                        "         (  \n" +
                        "          (("+latitude+"-latitude)*PI()*12656/180) \n" +
                        "          *  \n" +
                        "          (("+latitude+"-latitude)*PI()*12656/180)  \n" +
                        "         )  \n     " +
                        "   )<"+ RANGE);

                if ((!Objects.isNull( queryResult )) && queryResult.size() > 0) {
                    result.put( "province", queryResult.get(0).get("province") );
                    result.put( "city", queryResult.get(0).get("city") );
                    result.put( "country", country );
                }
            }
        } catch (NullPointerException e) {
            log.error( "GeoLite2-mmdb search Exception", e );
        } catch (IOException io) {
            log.error( "Get GeoLite2-Country.mmdb file Exception", io );
        } catch (SQLException e) {
            log.error( "数据库操作异常", e );
        }
        result.computeIfAbsent("province",(k)->UN_KNOWN);
        result.computeIfAbsent("city",(k)->UN_KNOWN);
        result.computeIfAbsent("country",(k)->UN_KNOWN);
        return result;
    }

    @Override
    public void close() throws IOException {
        IoUtil.close(reader);
    }

    @Override
    protected void finalize() throws Throwable {
        close();
        super.finalize();
    }
}

注册到spring容器

@Bean
    public IpAddressHelper ipAddressHelper(@Qualifier("dcDb")Db Db){
        return new IpAddressHelper(Db);
    }

使用:

ipAddressHelper.getRegionOrWithCache("1.2.3.4".toString()) 

代码: https://gitee.com/nanfree/springboot_code_set