java通过IP解析地理位置
在项目开发中,需要在登录日志或者操作日志中记录客户端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 #返回状态码
- }
java获取IP归属地(省、市)
1、添加依赖
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.3</version>
- </dependency>
2、工具类代码
- package com.shucha.deveiface.biz.test;
-
-
- /**
- * @author tqf
- * @Description 根据ip获取归属地
- * @Version 1.0
- * @since 2022-05-27 10:11
- */
-
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.http.HttpUtil;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import com.itextpdf.text.log.Logger;
- import com.itextpdf.text.log.LoggerFactory;
- import lombok.Data;
- import org.apache.commons.lang3.StringUtils;
- import javax.servlet.http.HttpServletRequest;
- public class iptes {
- private static Logger logger = LoggerFactory.getLogger(iptes.class);
-
- /**
- * 获取IP地址
- *
- * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
- * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
- */
- 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();
- }
- } catch (Exception e) {
- logger.error("IPUtils ERROR ", e);
- }
-
- //使用代理,则获取第一个IP地址
- if(StringUtils.isEmpty(ip) ) {
- if(ip.indexOf(",") > 0) {
- ip = ip.substring(0, ip.indexOf(","));
- }
- }
-
- return ip;
- }
-
- /**
- * 根据ip获取归属地
- * @param ip
- * @return
- */
- public static IpAddress getAddress(String ip) {
- String url = "http://ip.ws.126.net/ipquery?ip=" + ip;
- String str = HttpUtil.get(url);
- if(!StrUtil.hasBlank(str)){
- String substring = str.substring(str.indexOf("{"), str.indexOf("}")+1);
- JSONObject jsonObject = JSON.parseObject(substring);
- String province = jsonObject.getString("province");
- String city = jsonObject.getString("city");
- IpAddress ipAddress = new IpAddress();
- ipAddress.setProvince(province);
- ipAddress.setCity(city);
- System.out.println("ip:"+ ip + ",省份:" + province + ",城市:" + city);
- return ipAddress;
- }
- return null;
- }
-
- @Data
- public static class IpAddress{
- private String province;
- private String city;
- }
-
- public static void main(String[] args) {
- System.out.println(getAddress("36.25.225.250"));
- }
-
- }
3、测试结果
测试ip:36.25.225.250
返回数据:
ip:36.25.225.250,省份:浙江省,城市:湖州市
iptes.IpAddress(province=浙江省, city=湖州市)

总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。