实现前提:
1:下载ip2region.xdb文件
lionsoul2014/ip2region:Ip2region (2.0 - xdb) 是一个离线IP地址管理与定位框架,能够支持数十亿级别的数据段,并实现十微秒级的搜索性能。它为多种编程语言提供了xdb引擎实现。_Go - GitCode开源社区Ip2region (2.0 - xdb) 是一个离线IP地址管理与定位框架,能够支持数十亿级别的数据段,并实现十微秒级的搜索性能。它为多种编程语言提供了xdb引擎实现。https://gitcode.com/lionsoul2014/ip2region/overview2:安装依赖(注意这里的版本号,1开头的版本号和我这个版本号有区别,实现代码也是不同的)
<!--ip2region IP地址定位库-->
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.6.5</version>
</dependency>
实现步骤:
1:通过HttpServletRequest获取IP地址
/**
* 在 Nginx 等代理之后获取用户真实 IP 地址
* @return 用户的真实 IP 地址
*/
public static String getIpAddress(HttpServletRequest request) {
if (request == null) {
return null;
}
String ip = request.getHeader("x-forwarded-for");
if (isIpaddress(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (isIpaddress(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (isIpaddress(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (isIpaddress(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (isIpaddress(ip)) {
ip = request.getRemoteAddr();
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
//根据网卡取本机配置的IP
try {
InetAddress inet = InetAddress.getLocalHost();
ip = inet.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
return ip;
}
2:在服务启动时加载 ip2region.db 到内存中(解决打包 jar 后找不到 ip2region.db 的问题)
@PostConstruct
private static void initIp2regionResource() {
try {
InputStream inputStream = new ClassPathResource("/ip/ip2region.xdb").getInputStream();
byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream);
// 创建一个完全基于内存的查询对象(请自行创建静态变量:Searcher searcher )
searcher = Searcher.newWithBuffer(dbBinStr);
} catch (Exception e) {
e.printStackTrace();
}
}
3:根据ip获取属地
public static String getIpPossessionByFile(String ip,Integer type) {
if (StringUtils.isNotEmpty(ip)) {
try {
long sTime = System.nanoTime();
String region = searcher.search(ip);
long cost = TimeUnit.NANOSECONDS.toMicros(System.nanoTime() - sTime);
region = region.replace("|0", "");//去掉特殊字符
log.info("{地区: {}, IO操作数: {}, 耗时: {} μs}", region, searcher.getIOCount(), cost);
return region;
} catch (Exception e) {
log.error("获取IP地址异常:{} ", e.getMessage());
throw new RuntimeException("获取IP地址异常");
}
}
return "未知";
}
注意考虑多并发的情况!!!