1.通过市面上解析ip的架包进行实现
引入ip2region
<dependency>
<groupId>org.lionsoul</groupId>
<artifactId>ip2region</artifactId>
<version>2.7.0</version>
</dependency>
2.通过解析HttpServletRequest请求头,获取用户在访问api时网络ip地址
public static String getIpAddress(HttpServletRequest request) {
String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (LOCALHOST.equals(ipAddress)) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
ipAddress = inet.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
// 对于通过多个代理转发的情况,取第一个非unknown的IP地址。
// 这里假设第一个IP为真实IP,后面的为代理IP。
if (ipAddress != null && ipAddress.length() > 15) {
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
return ipAddress;
}
3.通过ip2region中提供的方法对ip进行解析,需要借助该项目提供的文件进行辅助解析。
去官网下载该文件
4.实现通过ip获取地址信息代码
public static IpLocation getLocation(String ip) {
IpLocation location = new IpLocation();
location.setIp(ip);
try (InputStream inputStream = IpUtil.class.getResourceAsStream("/ip2region.xdb");) {
byte[] bytes = IoUtil.readBytes(inputStream);
Searcher searcher = Searcher.newWithBuffer(bytes);
String region = searcher.search(ip);
if (StrUtil.isNotBlank(region)) {
// xdb返回格式 国家|区域|省份|城市|ISP,
// 只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0
String[] result = region.split("\\|");
location.setCountry(ZERO.equals(result[0])? StrUtil.EMPTY:result[0]);
location.setProvince(ZERO.equals(result[2])?StrUtil.EMPTY:result[2]);
location.setCity(ZERO.equals(result[3])?StrUtil.EMPTY:result[3]);
location.setIsp(ZERO.equals(result[4])?StrUtil.EMPTY:result[4]);
}
searcher.close();
} catch (Exception e) {
log.error("ip地址解析异常,error:{}",e);
return location;
}
return location;
}
测试结果;
完整代码如下:
package com.zbkj.common.utils;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.zbkj.common.model.user.IpLocation;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import javax.servlet.http.HttpServletRequest;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author: 崔思豪
* @create: 2024-05-08 13:18
*/
@Slf4j
public class IpUtil {
/**
* 字符常量0
*/
private static final String ZERO="0";
/**
* 本级ip
*/
private static final String LOCALHOST="127.0.0.1";
/**
* 获取客户端的IP地址
*/
public static String getIpAddress(HttpServletRequest request) {
String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (LOCALHOST.equals(ipAddress)) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
ipAddress = inet.getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
// 对于通过多个代理转发的情况,取第一个非unknown的IP地址。
// 这里假设第一个IP为真实IP,后面的为代理IP。
if (ipAddress != null && ipAddress.length() > 15) {
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
return ipAddress;
}
/**
* 根据iP获取归属地信息
* @return
*/
public static IpLocation getLocation(String ip) {
IpLocation location = new IpLocation();
location.setIp(ip);
try (InputStream inputStream = IpUtil.class.getResourceAsStream("/ip2region.xdb");) {
byte[] bytes = IoUtil.readBytes(inputStream);
Searcher searcher = Searcher.newWithBuffer(bytes);
String region = searcher.search(ip);
if (StrUtil.isNotBlank(region)) {
// xdb返回格式 国家|区域|省份|城市|ISP,
// 只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,后前的选项全部是0
String[] result = region.split("\\|");
location.setCountry(ZERO.equals(result[0])? StrUtil.EMPTY:result[0]);
location.setProvince(ZERO.equals(result[2])?StrUtil.EMPTY:result[2]);
location.setCity(ZERO.equals(result[3])?StrUtil.EMPTY:result[3]);
location.setIsp(ZERO.equals(result[4])?StrUtil.EMPTY:result[4]);
}
searcher.close();
} catch (Exception e) {
log.error("ip地址解析异常,error:{}",e);
return location;
}
return location;
}
public static void main(String[] args) {
IpLocation ipLocation = getLocation("114.114.114.114");
System.out.println(ipLocation.toString());
}
}
其中IpLocation 类如下
public class IpLocation implements Serializable {
@ApiModelProperty("ip地址")
private String ip;
@ApiModelProperty("国家")
private String country;
@ApiModelProperty("省")
private String province;
@ApiModelProperty("省")
private String city;
@ApiModelProperty("服务商")
private String isp;
}