java通过IP解析地理位置
文章目录
- java通过IP解析地理位置
- 一、获取IP地址
- 二、百度普通IP定位API获取地理位置
在项目开发中,需要在登录日志或者操作日志中记录客户端ip所在的地理位置。目前根据ip定位地理位置的第三方api有好几个,淘宝、新浪、百度等,这三种其实也有些缺点的:淘宝,开始几次可以成功根据ip获取对应地理位置,但后面就莫名其妙开始不行,直接通过浏览器获取又可以;新浪,之前一直可以,但最近不知道为什么不行了,访问直接报错(可能api修改了或者取消了吧);百度,需要申请百度地图开发者平台的开发者账号,请求时接口中需要加上百度提供的秘钥等信息,好像不能定位国外的ip,但是针对国内的可以使用。在此整理一下,便于后期使用。
百度Web服务API-普通IP定位:http://lbsyun.baidu.com/index.php?title=webapi/ip-api
根据以上使用指南,注册百度账号,成为地图开放平台开发者,获取密钥(AK),根据服务文档使用。
一、获取IP地址
java IP地址工具类,java IP地址获取,java获取客户端IP地址
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import javax.servlet.http.HttpServletRequest;
public class IpUtils {
private static final String[] HEADERS = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR",
"X-Real-IP"
};
/**
* 判断ip是否为空,空返回true
* @param ip
* @return
*/
public static boolean isEmptyIp(final String ip){
return (ip == null || ip.length() == 0 || ip.trim().equals("") || "unknown".equalsIgnoreCase(ip));
}
/**
* 判断ip是否不为空,不为空返回true
* @param ip
* @return
*/
public static boolean isNotEmptyIp(final String ip){
return !isEmptyIp(ip);
}
/***
* 获取客户端ip地址(可以穿透代理)
* @param request HttpServletRequest
* @return
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = "";
for (String header : HEADERS) {
ip = request.getHeader(header);
if(isNotEmptyIp(ip)) {
break;
}
}
if(isEmptyIp(ip)){
ip = request.getRemoteAddr();
}
if(isNotEmptyIp(ip) && ip.contains(",")){
ip = ip.split(",")[0];
}
if("0:0:0:0:0:0:0:1".equals(ip)){
ip = "127.0.0.1";
}
return ip;
}
/**
* 获取本机的局域网ip地址,兼容Linux
* @return String
* @throws Exception
*/
public String getLocalHostIP() throws Exception{
Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
String localHostAddress = "";
while(allNetInterfaces.hasMoreElements()){
NetworkInterface networkInterface = allNetInterfaces.nextElement();
Enumeration<InetAddress> address = networkInterface.getInetAddresses();
while(address.hasMoreElements()){
InetAddress inetAddress = address.nextElement();
if(inetAddress != null && inetAddress instanceof Inet4Address){
localHostAddress = inetAddress.getHostAddress();
}
}
}
return localHostAddress;
}
}
二、百度普通IP定位API获取地理位置
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.json.JSONException;
import org.json.JSONObject;
public class Ip2LocationViaBaidu {
/**
* 根据IP查询地理位置
* @param ip
* 查询的地址
* @return status
* 0:正常
* 1:API查询失败
* 2:API返回数据不完整
* @throws IOException
* @throws JSONException
*/
public static Object[] getLocation(String ip) throws IOException, JSONException {
String lng = null;// 经度
String lat = null;// 纬度
String province=null;//省
String city = null;// 城市名
String status = "0";// 成功
String ipString = null;
String jsonData = ""; // 请求服务器返回的json字符串数据
try {
ipString = java.net.URLEncoder.encode(ip, "UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
/*
* 请求URL
http://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll //HTTP协议
https://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll //HTTPS协议
*/
String key = "*************";// 百度密钥(AK),此处换成自己的AK
String url = String.format("https://api.map.baidu.com/location/ip?ak=%s&ip=%s&coor=bd09ll", key, ipString);// 百度普通IP定位API
URL myURL = null;
URLConnection httpsConn = null;
try {
myURL = new URL(url);
} catch (MalformedURLException e) {
e.printStackTrace();
}
InputStreamReader insr = null;
BufferedReader br = null;
try {
httpsConn = (URLConnection) myURL.openConnection();// 不使用代理
if (httpsConn != null) {
insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
br = new BufferedReader(insr);
String data = null;
int count = 1;
while ((data = br.readLine()) != null) {
jsonData += data;
}
JSONObject jsonObj = new JSONObject(jsonData);
if ("0".equals(jsonObj.getString("status"))) {
province = jsonObj.getJSONObject("content").getJSONObject("address_detail").getString("province");
city = jsonObj.getJSONObject("content").getJSONObject("address_detail").getString("city");
lng = jsonObj.getJSONObject("content").getJSONObject("point").getString("x");
lat = jsonObj.getJSONObject("content").getJSONObject("point").getString("y");
if (city.isEmpty() || lng.isEmpty() || lat.isEmpty()) {
status = "2";// API返回数据不完整
}
} else {
status = "1";// API查询失败
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (insr != null) {
insr.close();
}
if (br != null) {
br.close();
}
}
return new Object[] { status, province, city, lng, lat };
}
}
把上边的百度密钥换成你自己的,下边是API返回的json数据格式。
{
address: "CN|北京|北京|None|CHINANET|1|None", #地址
content: #详细内容
{
address: "北京市", #简要地址
address_detail: #详细地址信息
{
city: "北京市", #城市
city_code: 131, #百度城市代码
district: "", #区县
province: "北京市", #省份
street: "", #街道
street_number: "" #门址
},
point: #当前城市中心点
{
x: "116.39564504",
y: "39.92998578"
}
},
status: 0 #返回状态码
}
回到顶部