一、简介
ip2region - 准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB,提供了java、php、c、python、nodejs、golang、c#等查询绑定和Binary,B树,内存三种查询算法。
二、ip2region的使用
1、引入依赖
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
2、下载ip2region.db
这个可以在gitee仓库(https://gitee.com/lionsoul/ip2region)下载,在项目的data目录下。
3、IpUtils工具类
我封装了一个IpUtils工具类,主要有两个方法,一个是去获取请求中的真实客户端ip,一个是通过ip获取城市信息。
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* IP城市定位
*
* @author
* @Date 2021/1/1
*/
@Slf4j
public class IPUtils {
private static final String DB_PATH = "C:\\Users\\yanyunfan\\Downloads\\ip2region.db";
private static final String DEFAULT_CITY_NAME = "未知";
/**
* 获取城市信息
*
* @param ip ip
* @param algorithm 算法
* @return
*/
public static String getIpAddress(String ip, int algorithm) {
if (Util.isIpAddress(ip)) {
return DEFAULT_CITY_NAME;
} else if ("127.0.0.1".equals(ip) || StringUtils.startsWith(ip, "192.168")) {
return "内网IP";
}
// 查询算法B-tree, Binary, Memory
DbSearcher searcher = null;
try {
DbConfig config = new DbConfig();
searcher = new DbSearcher(config, DB_PATH);
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:
default:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
}
DataBlock dataBlock = (DataBlock) method.invoke(searcher, ip);
List<String> list = Arrays.asList(dataBlock.getRegion().split("\\|")).stream().filter(s -> !"0".equals(s)).collect(Collectors.toList());
String ipAddress = StringUtils.join(list, ",");
return ipAddress;
} catch (Exception e) {
log.error("获取城市信息失败:", e);
} finally {
try {
searcher.close();
} catch (IOException e) {
}
}
return DEFAULT_CITY_NAME;
}
/**
* 获取客户端ip
*
* @param request 请求
* @return
*/
public static String getClientIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
} else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
} else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
} else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
} else if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
public static void main(String[] args) {
String ip = "1.80.0.0";
String cityIpString = getIpAddress(ip, 2);
System.out.println(cityIpString);
}
}
控制台输出:
中国,陕西省,西安市,电信