经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Java » 查看文章
java如何通过IP解析地理位置
来源:jb51  时间:2023/2/15 9:19:36  对本文有异议

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地址

  1. import java.net.Inet4Address;
  2. import java.net.InetAddress;
  3. import java.net.NetworkInterface;
  4. import java.util.Enumeration;
  5. import javax.servlet.http.HttpServletRequest;
  6. public class IpUtils {
  7. private static final String[] HEADERS = {
  8. "X-Forwarded-For",
  9. "Proxy-Client-IP",
  10. "WL-Proxy-Client-IP",
  11. "HTTP_X_FORWARDED_FOR",
  12. "HTTP_X_FORWARDED",
  13. "HTTP_X_CLUSTER_CLIENT_IP",
  14. "HTTP_CLIENT_IP",
  15. "HTTP_FORWARDED_FOR",
  16. "HTTP_FORWARDED",
  17. "HTTP_VIA",
  18. "REMOTE_ADDR",
  19. "X-Real-IP"
  20. };
  21. /**
  22. * 判断ip是否为空,空返回true
  23. * @param ip
  24. * @return
  25. */
  26. public static boolean isEmptyIp(final String ip){
  27. return (ip == null || ip.length() == 0 || ip.trim().equals("") || "unknown".equalsIgnoreCase(ip));
  28. }
  29. /**
  30. * 判断ip是否不为空,不为空返回true
  31. * @param ip
  32. * @return
  33. */
  34. public static boolean isNotEmptyIp(final String ip){
  35. return !isEmptyIp(ip);
  36. }
  37. /***
  38. * 获取客户端ip地址(可以穿透代理)
  39. * @param request HttpServletRequest
  40. * @return
  41. */
  42. public static String getIpAddress(HttpServletRequest request) {
  43. String ip = "";
  44. for (String header : HEADERS) {
  45. ip = request.getHeader(header);
  46. if(isNotEmptyIp(ip)) {
  47. break;
  48. }
  49. }
  50. if(isEmptyIp(ip)){
  51. ip = request.getRemoteAddr();
  52. }
  53. if(isNotEmptyIp(ip) && ip.contains(",")){
  54. ip = ip.split(",")[0];
  55. }
  56. if("0:0:0:0:0:0:0:1".equals(ip)){
  57. ip = "127.0.0.1";
  58. }
  59. return ip;
  60. }
  61. /**
  62. * 获取本机的局域网ip地址,兼容Linux
  63. * @return String
  64. * @throws Exception
  65. */
  66. public String getLocalHostIP() throws Exception{
  67. Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
  68. String localHostAddress = "";
  69. while(allNetInterfaces.hasMoreElements()){
  70. NetworkInterface networkInterface = allNetInterfaces.nextElement();
  71. Enumeration<InetAddress> address = networkInterface.getInetAddresses();
  72. while(address.hasMoreElements()){
  73. InetAddress inetAddress = address.nextElement();
  74. if(inetAddress != null && inetAddress instanceof Inet4Address){
  75. localHostAddress = inetAddress.getHostAddress();
  76. }
  77. }
  78. }
  79. return localHostAddress;
  80. }
  81. }

百度普通IP定位API获取地理位置

  1. import java.io.BufferedReader;
  2. import java.io.IOException;
  3. import java.io.InputStreamReader;
  4. import java.io.UnsupportedEncodingException;
  5. import java.net.MalformedURLException;
  6. import java.net.URL;
  7. import java.net.URLConnection;
  8. import org.json.JSONException;
  9. import org.json.JSONObject;
  10. public class Ip2LocationViaBaidu {
  11. /**
  12. * 根据IP查询地理位置
  13. * @param ip
  14. * 查询的地址
  15. * @return status
  16. * 0:正常
  17. * 1:API查询失败
  18. * 2:API返回数据不完整
  19. * @throws IOException
  20. * @throws JSONException
  21. */
  22. public static Object[] getLocation(String ip) throws IOException, JSONException {
  23. String lng = null;// 经度
  24. String lat = null;// 纬度
  25. String province=null;//省
  26. String city = null;// 城市名
  27. String status = "0";// 成功
  28. String ipString = null;
  29. String jsonData = ""; // 请求服务器返回的json字符串数据
  30. try {
  31. ipString = java.net.URLEncoder.encode(ip, "UTF-8");
  32. } catch (UnsupportedEncodingException e1) {
  33. e1.printStackTrace();
  34. }
  35. /*
  36. * 请求URL
  37. http://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll //HTTP协议
  38. https://api.map.baidu.com/location/ip?ak=您的AK&ip=您的IP&coor=bd09ll //HTTPS协议
  39. */
  40. String key = "*************";// 百度密钥(AK),此处换成自己的AK
  41. String url = String.format("https://api.map.baidu.com/location/ip?ak=%s&ip=%s&coor=bd09ll", key, ipString);// 百度普通IP定位API
  42. URL myURL = null;
  43. URLConnection httpsConn = null;
  44. try {
  45. myURL = new URL(url);
  46. } catch (MalformedURLException e) {
  47. e.printStackTrace();
  48. }
  49. InputStreamReader insr = null;
  50. BufferedReader br = null;
  51. try {
  52. httpsConn = (URLConnection) myURL.openConnection();// 不使用代理
  53. if (httpsConn != null) {
  54. insr = new InputStreamReader(httpsConn.getInputStream(), "UTF-8");
  55. br = new BufferedReader(insr);
  56. String data = null;
  57. int count = 1;
  58. while ((data = br.readLine()) != null) {
  59. jsonData += data;
  60. }
  61. JSONObject jsonObj = new JSONObject(jsonData);
  62. if ("0".equals(jsonObj.getString("status"))) {
  63. province = jsonObj.getJSONObject("content").getJSONObject("address_detail").getString("province");
  64. city = jsonObj.getJSONObject("content").getJSONObject("address_detail").getString("city");
  65. lng = jsonObj.getJSONObject("content").getJSONObject("point").getString("x");
  66. lat = jsonObj.getJSONObject("content").getJSONObject("point").getString("y");
  67. if (city.isEmpty() || lng.isEmpty() || lat.isEmpty()) {
  68. status = "2";// API返回数据不完整
  69. }
  70. } else {
  71. status = "1";// API查询失败
  72. }
  73. }
  74. } catch (IOException e) {
  75. e.printStackTrace();
  76. } finally {
  77. if (insr != null) {
  78. insr.close();
  79. }
  80. if (br != null) {
  81. br.close();
  82. }
  83. }
  84. return new Object[] { status, province, city, lng, lat };
  85. }
  86. }

把上边的百度密钥换成你自己的,下边是API返回的json数据格式。

  1. {
  2. address: "CN|北京|北京|None|CHINANET|1|None", #地址
  3. content: #详细内容
  4. {
  5. address: "北京市", #简要地址
  6. address_detail: #详细地址信息
  7. {
  8. city: "北京市", #城市
  9. city_code: 131, #百度城市代码
  10. district: "", #区县
  11. province: "北京市", #省份
  12. street: "", #街道
  13. street_number: "" #门址
  14. },
  15. point: #当前城市中心点
  16. {
  17. x: "116.39564504",
  18. y: "39.92998578"
  19. }
  20. },
  21. status: 0 #返回状态码
  22. }

java获取IP归属地(省、市)

1、添加依赖

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.3</version>
  5. </dependency>

2、工具类代码

  1. package com.shucha.deveiface.biz.test;
  2. /**
  3. * @author tqf
  4. * @Description 根据ip获取归属地
  5. * @Version 1.0
  6. * @since 2022-05-27 10:11
  7. */
  8. import cn.hutool.core.util.StrUtil;
  9. import cn.hutool.http.HttpUtil;
  10. import com.alibaba.fastjson.JSON;
  11. import com.alibaba.fastjson.JSONObject;
  12. import com.itextpdf.text.log.Logger;
  13. import com.itextpdf.text.log.LoggerFactory;
  14. import lombok.Data;
  15. import org.apache.commons.lang3.StringUtils;
  16. import javax.servlet.http.HttpServletRequest;
  17. public class iptes {
  18. private static Logger logger = LoggerFactory.getLogger(iptes.class);
  19. /**
  20. * 获取IP地址
  21. *
  22. * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
  23. * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
  24. */
  25. public static String getIpAddr(HttpServletRequest request) {
  26. String ip = null;
  27. try {
  28. ip = request.getHeader("x-forwarded-for");
  29. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  30. ip = request.getHeader("Proxy-Client-IP");
  31. }
  32. if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  33. ip = request.getHeader("WL-Proxy-Client-IP");
  34. }
  35. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  36. ip = request.getHeader("HTTP_CLIENT_IP");
  37. }
  38. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  39. ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  40. }
  41. if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
  42. ip = request.getRemoteAddr();
  43. }
  44. } catch (Exception e) {
  45. logger.error("IPUtils ERROR ", e);
  46. }
  47. //使用代理,则获取第一个IP地址
  48. if(StringUtils.isEmpty(ip) ) {
  49. if(ip.indexOf(",") > 0) {
  50. ip = ip.substring(0, ip.indexOf(","));
  51. }
  52. }
  53. return ip;
  54. }
  55. /**
  56. * 根据ip获取归属地
  57. * @param ip
  58. * @return
  59. */
  60. public static IpAddress getAddress(String ip) {
  61. String url = "http://ip.ws.126.net/ipquery?ip=" + ip;
  62. String str = HttpUtil.get(url);
  63. if(!StrUtil.hasBlank(str)){
  64. String substring = str.substring(str.indexOf("{"), str.indexOf("}")+1);
  65. JSONObject jsonObject = JSON.parseObject(substring);
  66. String province = jsonObject.getString("province");
  67. String city = jsonObject.getString("city");
  68. IpAddress ipAddress = new IpAddress();
  69. ipAddress.setProvince(province);
  70. ipAddress.setCity(city);
  71. System.out.println("ip:"+ ip + ",省份:" + province + ",城市:" + city);
  72. return ipAddress;
  73. }
  74. return null;
  75. }
  76. @Data
  77. public static class IpAddress{
  78. private String province;
  79. private String city;
  80. }
  81. public static void main(String[] args) {
  82. System.out.println(getAddress("36.25.225.250"));
  83. }
  84. }

3、测试结果

测试ip:36.25.225.250

返回数据:

ip:36.25.225.250,省份:浙江省,城市:湖州市                  

iptes.IpAddress(province=浙江省, city=湖州市)

总结

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号