之前从网上看了大多数都是调用淘宝的api来查询归属地,但是我试了各种方法,淘宝的一直返回301,返回结果中也没有新的请求地址。可能也是我调用方法不对吧,给大家分享一下另一种方式来查询ip归属地的方法
什么是ip2region
ip2region是一套准确率99.9%的ip地址定位库,0.0x毫秒级查询,数据库文件大小只有1.6M,提供了java, php, c, python,nodejs,golang查询绑定和Binary,B树,内存三种查询算法。需要的朋友可以下载!
99.9%准确率,定时更新:数据聚合了一些知名ip到地名查询提供商的数据,这些是他们官方的的准确率,经测试着实比纯真啥的准确多了。每次聚合一下数据需要1-2天,会不定时更新。
pom文件添加依赖
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>1.7.2</version>
</dependency>
下载:ip2region.db 地址库
https://pan.baidu.com/s/10uIcmXnEo3Yt4RgdNqouGA
提取码:8888
放在resources文件夹下
代码就简单了
package com.leimingtech.start.controller;
import com.leimingtech.start.service.StartLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@RestController
@Slf4j
public class StartController {
@Autowired
private StartLogService strartLogService;
@PostMapping("save")
public void startLog() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String ipAddr = getIpAddr(request);
log.info("ip:{}",ipAddr);
strartLogService.save(ipAddr);
}
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
if (StringUtils.isNotBlank(ip)) {
// 多次反向代理后会有多个IP值,第一个为真实IP。
int index = ip.indexOf(',');
if (index != -1) {
return ip.substring(0, index);
} else {
return ip;
}
}
} catch (Exception e) {
}
return ip;
}
}
package com.leimingtech.start.service.impl;
import cn.hutool.core.io.resource.ClassPathResource;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.leimingtech.start.dao.StartLogDao;
import com.leimingtech.start.entity.StartLogEntity;
import com.leimingtech.start.service.StartLogService;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.lang.reflect.Method;
import java.util.Date;
@Service
@Slf4j
public class StartLogServiceImpl implements StartLogService {
@Autowired
private StartLogDao startLogDao;
@Override
public void save(String ipAddr) {
String ipString = getCityInfo(ipAddr);
log.info("ip归属:{}",ipString);
StartLogEntity entity = StartLogEntity.builder().id(IdWorker.getId())
.area(ipString)
.ip(ipAddr)
.createDate(new Date())
.build();
startLogDao.insert(entity);
}
/**
* 根据ip获取详细地址
*/
public static String getCityInfo(String ip) {
DbSearcher searcher = null;
try {
String path = "ip2region/ip2region.db";
String name = "ip2region.db";
DbConfig config = new DbConfig();
File file = inputStreamToFile(new ClassPathResource(path).getStream(), name);
searcher = new DbSearcher(config, file.getPath());
Method method;
method = searcher.getClass().getMethod("btreeSearch", String.class);
DataBlock dataBlock;
dataBlock = (DataBlock) method.invoke(searcher, ip);
String address = dataBlock.getRegion().replace("0|", "");
char symbol = '|';
if (address.charAt(address.length() - 1) == symbol) {
address = address.substring(0, address.length() - 1);
}
return address.equals("内网IP|内网IP") ? "内网IP" : address;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (searcher != null) {
try {
searcher.close();
} catch (IOException ignored) {
}
}
}
return "";
}
/**
* inputStream 转 File
*/
public static File inputStreamToFile(InputStream ins, String name) throws Exception {
File file = new File(System.getProperty("java.io.tmpdir") + File.separator + name);
if (file.exists()) {
return file;
}
OutputStream os = new FileOutputStream(file);
int bytesRead;
int len = 8192;
byte[] buffer = new byte[len];
while ((bytesRead = ins.read(buffer, 0, len)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
return file;
}
}
返回格式
根据需要自己更改组合方式