記錄根據(jù)用戶ip地址獲取用戶所屬地
最近有個需求,需要根據(jù)用戶的登陸ip完成用戶所在地。
參考ip2region 最新版本的demo:https://gitee.com/lionsoul/ip2region/tree/master/binding/java
使用的內(nèi)存讀取的方式,代碼直接拷貝git上面的demo:
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
import org.lionsoul.ip2region.xdb.Searcher; import java.io.*; import java.util.concurrent.TimeUnit; public class SearcherTest { public static void main(String[] args) { String dbPath = "ip2region.xdb file path"; // 1、從 dbPath 加載整個 xdb 到內(nèi)存。 byte[] cBuff; try { cBuff = Searcher.loadContentFromFile(dbPath); } catch (Exception e) { System.out.printf("failed to load content from `%s`: %s\n", dbPath, e); return; } // 2、使用上述的 cBuff 創(chuàng)建一個完全基于內(nèi)存的查詢對象。 Searcher searcher; try { searcher = Searcher.newWithBuffer(cBuff); } catch (Exception e) { System.out.printf("failed to create content cached searcher: %s\n", e); return; } // 3、查詢 try { String ip = "1.2.3.4"; long sTime = System.nanoTime(); String region = searcher.search(ip); long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime)); System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost); } catch (Exception e) { System.out.printf("failed to search(%s): %s\n", ip, e); } // 4、關(guān)閉資源 - 該 searcher 對象可以安全用于并發(fā),等整個服務(wù)關(guān)閉的時候再關(guān)閉 searcher // searcher.close(); // 備注:并發(fā)使用,用整個 xdb 數(shù)據(jù)緩存創(chuàng)建的查詢對象可以安全的用于并發(fā),也就是你可以把這個 searcher 對象做成全局對象去跨線程訪問。 } }
自己的系統(tǒng)是windows的,把上面的dbPath換成本地的ip2region.xdb的絕對路徑,運行測試,一切正常。
但是打包部署到開發(fā)環(huán)境,發(fā)現(xiàn)一直獲取為空,并且拋出
failed to search(1.202.31.54): java.lang.ArrayIndexOutOfBoundsException
奇怪了,然后去git上面搜索。
https://gitee.com/lionsoul/ip2region/issues/I7GYFY
根據(jù)這個解決了,

原因是:https://github.com/lionsoul2014/ip2region/issues/279
因為maven resources 拷貝文件是默認會做 filter,會導(dǎo)致我們的文件發(fā)生變化,導(dǎo)致不能讀
順便拷貝下代碼:
package com.gwm.marketing.authcenter.util; @Component public class SearcherUtils { @Autowired private ResourceLoader resourceLoader; private static Logger logger = LoggerFactory.getLogger(SearcherUtils.class); public String searchIp(String ip){ try { logger.info("=============start========"); //這個是服務(wù)器讀取的方式,,如果是本地 windeos可以寫絕對路徑 Resource resource = resourceLoader.getResource("classpath:ip2region/ip2region.xdb"); if(resource == null || !resource.exists()){ return null; } logger.info("===========resource getUri=========" + resource.getURI()); logger.info("============resource fileName " + resource.getFilename()); //InputStream stream = ResourceUtil.getStream(dbPath); byte[] cBuff = IoUtil.readBytes(resource.getInputStream()); // 1、從 dbPath 加載整個 xdb 到內(nèi)存。 /*byte[] cBuff; try { cBuff = Searcher.loadContentFromFile(dbPath); } catch (Exception e) { System.out.printf("failed to load content from `%s`: %s\n", dbPath, e); return null; }*/ // 2、使用上述的 cBuff 創(chuàng)建一個完全基于內(nèi)存的查詢對象。 Searcher searcher; try { searcher = Searcher.newWithBuffer(cBuff); } catch (Exception e) { logger.error("獲取異常",e); System.out.printf("failed to create content cached searcher: %s\n", e); return null; } // 3、查詢 try { long sTime = System.nanoTime(); String region = searcher.search(ip); long cost = TimeUnit.NANOSECONDS.toMicros((long) (System.nanoTime() - sTime)); System.out.printf("{region: %s, ioCount: %d, took: %d μs}\n", region, searcher.getIOCount(), cost); return region; } catch (Exception e) { System.out.printf("failed to search(%s): %s\n", ip, e); } return null; } catch (Exception e) { logger.error("獲取地址異常",e); } return null; } /* public static void main(String[] args) { System.out.println(searchIp("121.237.31.134")); System.out.println(searchIp("47.122.18.76")); System.out.println(searchIp("123.114.36.50")); System.out.println(searchIp("35.187.132.16")); System.out.println(searchIp("49.35.162.6")); System.out.println(searchIp("5.188.210.227")); System.out.println(searchIp("64.233.173.10")); System.out.println(searchIp("74.125.151.127")); System.out.println(searchIp("74.125.212.221")); System.out.println(searchIp("95.184.60.224")); // 4、關(guān)閉資源 - 該 searcher 對象可以安全用于并發(fā),等整個服務(wù)關(guān)閉的時候再關(guān)閉 searcher // searcher.close(); // 備注:并發(fā)使用,用整個 xdb 數(shù)據(jù)緩存創(chuàng)建的查詢對象可以安全的用于并發(fā),也就是你可以把這個 searcher 對象做成全局對象去跨線程訪問。 }*/ }

浙公網(wǎng)安備 33010602011771號