0
篇帖子
数据分析不可避免经常遇到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())
本博客内所有原创和翻译的文章的版权归本人所有,允许第三方转载,但转载时请务必保留作者名,并注明出处链接,否则本人将保留追究其法律责任的权利。
「人生在世,留句话给我吧」