Java通过百度地图API获取定位(普通IP定位)的方法教程

 更新时间:2024年11月05日 11:28:57   作者:沐雨橙风ιε  
这篇文章主要介绍了Java通过百度地图API获取定位的方法教程,首先说明了实现这个功能的需求和初衷,然后详细描述了利用百度地图API实现这个功能的步骤,包括在百度地图开放平台的准备工作、学习官网API文档、修改API的AK配置、Java代码获取定位等,需要的朋友可以参考下

项目中有一个登录邮箱提醒的功能,需要根据IP地址获取定位信息,从而更好地提示用户账号登录的所在地。为此,花费了一些时间来实现这个功能。

搜索了一下,发现关于获取定位的文章说明都不够详细,于是决定自己创作一篇文章,希望能够帮助到有需求的小伙伴~

因为博主日常生活中用的导航APP就是百度地图,所以使用百度地图的API来实现这个功能。

百度地图开放平台

本篇文章都是围绕百度地图的开放平台官网的相关说明来展开的,访问下面的链接

百度地图开放平台 | 百度地图API SDK | 地图开发 这是开放平台的首页截图

开始前的准备工作

点击上方导航菜单的开发文档-Web服务API总览

 紧接着,点击左侧菜单中的定位,点击普通IP定位

然后根据开发文档的提示完成步骤1、2、3

学习官网API文档

最后点击步骤4,开始使用百度地图的API

如上图,文档已经给出了API的接口地址和参数说明,以及API接口返回的参数格式。

{
  "address": "CN|北京市|北京市|None|None|100|91",
  "content": {
    "address": "北京市",
    "address_detail": {
      "adcode": "110000",
      "city": "北京市",
      "city_code": 131,
      "district": "",
      "province": "北京市",
      "street": "",
      "street_number": ""
    },
    "point": {
      "x": "116.41338370",
      "y": "39.91092455"
    }
  },
  "status": 0
}

修改API的AK配置

在这里,需要修改一下创建的应用的相关设置。

点击上图的设置按钮来到这个页面,然后拉到页面的底部,修改应用的请求校验方式为sn校验方式,然后点击提交按钮。

把AK复制到示例代码的输入框中,点击确认按钮自动生成获取定位的Java代码,可以说非常方便。

Java代码获取定位

通过官网生成代码

新建一个类SearchHttpAK,把示例代码复制到SearchHttpAK类里,复制按钮在下图红框内。

调整之后的代码如下(真实的AK和SK都已经被博主替换了,这里的5个x改成自己的AK和SK就行了)。

package cn.edu.sgu.www.authority.util;

import org.springframework.web.util.UriUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 选择AK使用SN校验:
 * @author heyunlin
 * @version 1.0
 */
public class SearchHttpSN {

    public static String AK = "xxxxx";

    public static String SK = "xxxxx";

    public static String URL = "https://api.map.baidu.com/location/ip?";

    public static void main(String[] args) throws Exception {

        SearchHttpSN snCal = new SearchHttpSN();

        Map<String, String> params = new LinkedHashMap<>(4);
        
        params.put("ip", "111.206.214.37");
        params.put("coor", "bd09ll");
        params.put("ak", AK);

        params.put("sn", snCal.caculateSn());

        snCal.requestGetSN(URL, params);
    }

    /**
     * 选择了ak,使用SN校验:
     * 根据您选择的AK已为您生成调用代码
     * 检测您当前的AK设置了sn检验,本示例中已为您生成sn计算代码
     * @param strUrl
     * @param param
     * @throws Exception
     */
    public void requestGetSN(String strUrl, Map<String, String> param) throws Exception {
        if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) {
            return;
        }

        StringBuilder queryString = new StringBuilder();
        queryString.append(strUrl);
        
        for (Map.Entry<?, ?> pair : param.entrySet()) {
            queryString.append(pair.getKey()).append("=");
            // 第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            // queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8")).append("&");
        }

        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }

        java.net.URL url = new URL(queryString.toString());
        System.out.println(queryString.toString());
        URLConnection httpConnection = (HttpURLConnection) url.openConnection();
        httpConnection.connect();

        InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
        BufferedReader reader = new BufferedReader(isr);
        StringBuilder buffer = new StringBuilder();
        String line;
        
        while ((line = reader.readLine()) != null) {
            buffer.append(line);
        }
        
        reader.close();
        isr.close();
        
        System.out.println("SN: " + buffer);
    }

    public String caculateSn() throws UnsupportedEncodingException,
            NoSuchAlgorithmException {
        SearchHttpSN snCal = new SearchHttpSN();

        // 计算sn跟参数对出现顺序有关,get请求请使用LinkedHashMap保存<key,value>,该方法根据key的插入顺序排序;post请使用TreeMap保存<key,value>,该方法会自动将key按照字母a-z顺序排序。
        // 所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。
        // 以get请求为例:http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入顺序必须跟get请求中对应参数的出现顺序保持一致。
        Map<String, String> paramsMap = new LinkedHashMap<>(3);
        
        paramsMap.put("ip", "111.206.214.37");
        paramsMap.put("coor", "bd09ll");
        paramsMap.put("ak", AK);


        // 调用下面的toQueryString方法,对LinkedHashMap内所有value作utf8编码,拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
        String paramsStr = snCal.toQueryString(paramsMap);

        // 对paramsStr前面拼接上/geocoder/v2/?,后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
        String wholeStr = new String("/location/ip?" + paramsStr + SK);

        System.out.println(wholeStr);
        // 对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");

        // 调用下面的MD5方法得到最后的sn签名
        String sn = snCal.MD5(tempStr);
        System.out.println(sn);
        return sn;
    }

    // 对Map内所有value作utf8编码,拼接返回结果
    public String toQueryString(Map<?, ?> data) {
        StringBuilder queryString = new StringBuilder();
        
        for (Map.Entry<?, ?> pair : data.entrySet()) {
            queryString.append(pair.getKey()).append("=");
            // 第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            // queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8")).append("&");
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
    }

    // 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
    public String MD5(String md5) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuilder sb = new StringBuilder();

            for (byte b : array) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException ignored) { }
        
        return null;
    }
}

注意,不要修改这里的map的放入顺序,否则请求接口会报错~

Map<String, String> params = new LinkedHashMap<>(4);
        
params.put("ip", "111.206.214.37");
params.put("coor", "bd09ll");
params.put("ak", AK);

params.put("sn", snCal.caculateSn());

运行生成的代码

然后运行一下代码,如果能看到下面这样的运行结果,恭喜你,你已经成功了一大半~

不要纠结获取到的位置信息里很多16进制,因为马上就要把他转成一个自定义的实体类

创建接口返回对象

根据这个API返回的JSON格式字符串的结构,创建4个对应的实体类

Point.java

import lombok.Data;
/**
 * @author heyunlin
 * @version 1.0
 */
@Data
public class Point {
    private String x;
    private String y;
}

Location.java

import lombok.Data;
/**
 * @author heyunlin
 * @version 1.0
 */
@Data
public class Location {
    private Integer status;
    private String address;
    private Content content;
}

Content.java

import lombok.Data;
/**
 * @author heyunlin
 * @version 1.0
 */
@Data
public class Content {
    private Point point;
    private String address;
    private AddressDetail address_detail;
}

AddressDetail.java

import lombok.Data;
/**
 * @author heyunlin
 * @version 1.0
 */
@Data
public class AddressDetail {
    private String adcode;
    private String city;
    private String city_code;
    private String province;
    private String district;
    private String street;
    private String street_number;
}

将JSON字符串转成Location对象

修改一下部分方法的名称,然后把字符串通过fastjson的API转成Location对象

package cn.edu.sgu.www.authority.util;
import cn.edu.sgu.www.authority.location.Location;
import com.alibaba.fastjson.JSON;
import org.springframework.web.util.UriUtils;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * 选择AK使用SN校验:
 * @author heyunlin
 * @version 1.0
 */
public class SearchHttpSN {
    public static String AK = "xxxxx";
    public static String SK = "xxxxx";
    public static String URL = "https://api.map.baidu.com/location/ip?";
    public static void main(String[] args) throws Exception {
        String ip = "111.206.214.37";
        String location = getLocation(ip);
        System.out.println(JSON.parseObject(location, Location.class));
    }
    public static String getLocation(String ip) throws Exception {
        Map<String, String> params = new LinkedHashMap<>(4);
        params.put("ip", ip);
        params.put("coor", "bd09ll");
        params.put("ak", AK);
        params.put("sn", caculateSn());
        return getLocation(URL, params);
    }
    /**
     * 选择了ak,使用SN校验:
     * 根据您选择的AK已为您生成调用代码
     * 检测您当前的AK设置了sn检验,本示例中已为您生成sn计算代码
     * @param strUrl
     * @param param
     * @throws Exception
     */
    public static String getLocation(String strUrl, Map<String, String> param) throws Exception {
        if (strUrl == null || strUrl.length() <= 0 || param == null || param.size() <= 0) {
            return null;
        }
        StringBuilder queryString = new StringBuilder();
        queryString.append(strUrl);
        for (Map.Entry<?, ?> pair : param.entrySet()) {
            queryString.append(pair.getKey()).append("=");
            // 第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            // queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8")).append("&");
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        java.net.URL url = new URL(queryString.toString());
        System.out.println(queryString);
        URLConnection httpConnection = url.openConnection();
        httpConnection.connect();
        InputStreamReader isr = new InputStreamReader(httpConnection.getInputStream());
        BufferedReader reader = new BufferedReader(isr);
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        isr.close();
        return sb.toString();
    }
    public static String caculateSn() throws UnsupportedEncodingException {
        // 计算sn跟参数对出现顺序有关,get请求请使用LinkedHashMap保存<key,value>,该方法根据key的插入顺序排序;post请使用TreeMap保存<key,value>,该方法会自动将key按照字母a-z顺序排序。
        // 所以get请求可自定义参数顺序(sn参数必须在最后)发送请求,但是post请求必须按照字母a-z顺序填充body(sn参数必须在最后)。
        // 以get请求为例:http://api.map.baidu.com/geocoder/v2/?address=百度大厦&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入顺序必须跟get请求中对应参数的出现顺序保持一致。
        Map<String, String> paramsMap = new LinkedHashMap<>(3);
        paramsMap.put("ip", "111.206.214.37");
        paramsMap.put("coor", "bd09ll");
        paramsMap.put("ak", AK);
        // 调用下面的toQueryString方法,对LinkedHashMap内所有value作utf8编码,拼接返回结果address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourak
        String paramsStr = toQueryString(paramsMap);
        // 对paramsStr前面拼接上/geocoder/v2/?,后面直接拼接yoursk得到/geocoder/v2/?address=%E7%99%BE%E5%BA%A6%E5%A4%A7%E5%8E%A6&output=json&ak=yourakyoursk
        String wholeStr = new String("/location/ip?" + paramsStr + SK);
        System.out.println(wholeStr);
        // 对上面wholeStr再作utf8编码
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");
        // 调用下面的MD5方法得到最后的sn签名
        return MD5(tempStr);
    }
    // 对Map内所有value作utf8编码,拼接返回结果
    public static String toQueryString(Map<?, ?> data) {
        StringBuilder queryString = new StringBuilder();
        for (Map.Entry<?, ?> pair : data.entrySet()) {
            queryString.append(pair.getKey()).append("=");
            // 第一种方式使用的 jdk 自带的转码方式  第二种方式使用的 spring 的转码方法 两种均可
            // queryString.append(URLEncoder.encode((String) pair.getValue(), "UTF-8").replace("+", "%20") + "&");
            queryString.append(UriUtils.encode((String) pair.getValue(), "UTF-8")).append("&");
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
    }
    // 来自stackoverflow的MD5计算方法,调用了MessageDigest库函数,并把byte数组结果转换成16进制
    public static String MD5(String md5) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : array) {
                sb.append(Integer.toHexString((b & 0xFF) | 0x100), 1, 3);
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException ignored) { }
        return null;
    }
}

运行代码,效果如下:

在使用的时候,只需要传入IP地址即可获取到定位信息~

代码的最后优化

上面的代码已经是进行了一定的优化,除此之外,可以把AK和SK配置到application.yml中,可以动态地修改。最后重命名一下这个类,改成类似LocationUtils这样的名字。

总结

到此这篇关于Java通过百度地图API获取定位(普通IP定位)的文章就介绍到这了,更多相关Java百度地图API获取定位内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • WIN10系统中添加bat脚本重启jar服务

    WIN10系统中添加bat脚本重启jar服务

    在bat脚本中执行java服务,命令与cmd中类似,下面这篇文章主要给大家介绍了关于WIN10系统中添加bat脚本重启jar服务的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • 基于雪花算法实现增强版ID生成器详解

    基于雪花算法实现增强版ID生成器详解

    这篇文章主要为大家详细介绍了如何基于雪花算法实现增强版ID生成器,文中的示例代码讲解详细,对我们学习具有一定的借鉴价值,需要的可以了解一下
    2022-10-10
  • java循环结构、数组的使用小结

    java循环结构、数组的使用小结

    这篇文章主要介绍了java循环结构、数组的使用小结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • SpringBoot+websocket实现消息对话功能

    SpringBoot+websocket实现消息对话功能

    WebSocket是一种在Web应用程序中实现实时双向通信的技术,它可以用于在线游戏、在线聊天、推送通知、实时监控等,并且比传统的轮询技术更加高效和可靠,本文就给大家介绍基于SpringBoot+websocket实现消息对话功能,感兴趣的小伙伴可以自己动手试一试
    2023-09-09
  • Java中Scanner类使用保姆级教程

    Java中Scanner类使用保姆级教程

    JavaSE在java.util类库中提供了一个专门用于输入操作的类Scanner类,可以使用该类创建一个对象,然后利用该对象的相关方法从键盘上读取数据,下面这篇文章主要给大家介绍了关于Java中Scanner类使用的相关资料,需要的朋友可以参考下
    2023-04-04
  • java实现随机数生成器

    java实现随机数生成器

    这篇文章主要为大家详细介绍了java实现随机数生成器,随机数生成小程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • JavaWEB项目之如何配置动态数据源

    JavaWEB项目之如何配置动态数据源

    这篇文章主要介绍了JavaWEB项目之如何配置动态数据源问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • 利用Java代码实现区块链技术

    利用Java代码实现区块链技术

    这篇文章主要介绍了利用Java代码实现区块链技术,区块链的应用范围几乎无穷无尽,关于区块链是如何运作的,下文来看看具体的内容介绍吧,需要的朋友可以参考一下
    2022-04-04
  • springboot中filter的用法详解

    springboot中filter的用法详解

    本篇文章主要介绍了springboot中filter的用法详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-11-11
  • spring boot 监听容器启动代码实例

    spring boot 监听容器启动代码实例

    这篇文章主要介绍了spring boot 监听容器启动代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10

最新评论