|
@@ -1,10 +1,18 @@
|
|
|
package com.qmth.themis.common.util;
|
|
|
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
-
|
|
|
+import com.qmth.themis.common.exception.BusinessException;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.lionsoul.ip2region.xdb.Searcher;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.io.File;
|
|
|
+import java.net.URL;
|
|
|
+import java.util.Objects;
|
|
|
|
|
|
public class IpUtil {
|
|
|
+ private final static Logger log = LoggerFactory.getLogger(IpUtil.class);
|
|
|
|
|
|
/**
|
|
|
* 获取过程ip(默认不包含代理ip)
|
|
@@ -54,5 +62,128 @@ public class IpUtil {
|
|
|
}
|
|
|
return ip;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 根据IP地址获取城市
|
|
|
+// *
|
|
|
+// * @param ip 如果放在服务器读取不了,两种方式
|
|
|
+// * 1.可以在服务器上创建文件,ip2region.db这个放在文件里面,然后开始读取
|
|
|
+// * 2.可以整个配置文件,在配置配置目录,然后读取配置文件
|
|
|
+// * @return
|
|
|
+// */
|
|
|
+// public static String getCityInfo(String ip) throws IOException {
|
|
|
+// URL url = IpUtil.class.getClassLoader().getResource("ip2region.db");
|
|
|
+// File file = Objects.nonNull(url) ? new File(url.getFile()) : null;
|
|
|
+// if (Objects.isNull(file)) {
|
|
|
+// return null;
|
|
|
+// }
|
|
|
+// if (!file.exists()) {
|
|
|
+// log.error("Error: Invalid ip2region.db file, filePath:" + file.getPath());
|
|
|
+// return null;
|
|
|
+// }
|
|
|
+// //查询算法
|
|
|
+// int algorithm = DbSearcher.BTREE_ALGORITHM; //B-tree
|
|
|
+// //DbSearcher.BINARY_ALGORITHM //Binary
|
|
|
+// //DbSearcher.MEMORY_ALGORITYM //Memory
|
|
|
+// try {
|
|
|
+// DbConfig config = new DbConfig();
|
|
|
+// DbSearcher searcher = new DbSearcher(config, file.getPath());
|
|
|
+// 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:
|
|
|
+// method = searcher.getClass().getMethod("memorySearch", String.class);
|
|
|
+// break;
|
|
|
+// default:
|
|
|
+// return null;
|
|
|
+// }
|
|
|
+// DataBlock dataBlock;
|
|
|
+// if (!Util.isIpAddress(ip)) {
|
|
|
+// log.error("Error: Invalid ip address");
|
|
|
+// return null;
|
|
|
+// }
|
|
|
+// dataBlock = (DataBlock) method.invoke(searcher, ip);
|
|
|
+// return dataBlock.getRegion();
|
|
|
+// } catch (Exception e) {
|
|
|
+// e.printStackTrace();
|
|
|
+// }
|
|
|
+// return null;
|
|
|
+// }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取全局searcher
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static Searcher getSearcher() {
|
|
|
+ URL url = IpUtil.class.getClassLoader().getResource("ip2region.xdb");
|
|
|
+ File file = Objects.nonNull(url) ? new File(url.getFile()) : null;
|
|
|
+ if (Objects.isNull(file)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ if (!file.exists()) {
|
|
|
+ log.error("Error: Invalid ip2region.xdb file, filePath:{}", file.getPath());
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ // 1、从 dbPath 加载整个 xdb 到内存。
|
|
|
+ byte[] cBuff;
|
|
|
+ try {
|
|
|
+ cBuff = Searcher.loadContentFromFile(file.getPath());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("加载ip离线数据失败", e);
|
|
|
+ if (e instanceof BusinessException) {
|
|
|
+ throw new BusinessException(e.getMessage());
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
|
|
|
+ Searcher searcher;
|
|
|
+ try {
|
|
|
+ searcher = Searcher.newWithBuffer(cBuff);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("failed to create content cached searcher", e);
|
|
|
+ if (e instanceof BusinessException) {
|
|
|
+ throw new BusinessException(e.getMessage());
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return searcher;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取ip信息
|
|
|
+ *
|
|
|
+ * @param searcher
|
|
|
+ * @param ip
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static String getIpInfo(Searcher searcher, String ip) {
|
|
|
+ String region = null;
|
|
|
+ // 3、查询
|
|
|
+ try {
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+ region = searcher.search(ip);
|
|
|
+ long end = System.currentTimeMillis();
|
|
|
+ log.info("region: {}, ioCount: {}, 耗时: {} 秒", region, searcher.getIOCount(), (end - start) / 1000);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("failed to search", e);
|
|
|
+ if (e instanceof BusinessException) {
|
|
|
+ throw new BusinessException(e.getMessage());
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException(e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 4、关闭资源 - 该 searcher 对象可以安全用于并发,等整个服务关闭的时候再关闭 searcher
|
|
|
+ // searcher.close();
|
|
|
+ // 备注:并发使用,用整个 xdb 数据缓存创建的查询对象可以安全的用于并发,也就是你可以把这个 searcher 对象做成全局对象去跨线程访问。
|
|
|
+ return region;
|
|
|
+ }
|
|
|
}
|