Java通过百度地图API获取定位-普通IP定位

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

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

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

目录

百度地图开放平台

开始前的准备工作

学习官网API文档

修改API的AK配置

Java代码获取定位

通过官网生成代码

运行生成的代码

创建接口返回对象

Point.java

Location.java

Content.java

AddressDetail.java

将JSON字符串转成Location对象

代码的最后优化


百度地图开放平台

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

百度地图开放平台 | 百度地图API SDK | 地图开发icon-default.png?t=N7T8https://lbsyun.baidu.com/index.php?title=%E9%A6%96%E9%A1%B5这是开放平台的首页截图

开始前的准备工作

点击上方导航菜单的开发文档-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=yourakString 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=yourakyourskString 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=yourakString 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=yourakyourskString 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这样的名字。

好了,文章就分享到这里了,看完如果觉得对你有所帮助,不要忘了点赞+收藏哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3030213.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【C++ 内存管理】深拷贝和浅拷贝你了解吗?

文章目录 1.深拷贝2.浅拷贝3.深拷贝和浅拷贝 1.深拷贝 &#x1f34e; 深拷⻉: 是对对象的完全独⽴复制&#xff0c;包括对象内部动态分配的资源。在深拷⻉中&#xff0c;不仅复制对象的值&#xff0c;还会复制对象所指向的堆上的数据。 特点&#xff1a; &#x1f427;① 复制对…

1.理解机器学习

本文参考于&#xff1a;https://hands1ml.apachecn.org/1/ 大多数人听到“机器学习”&#xff0c;往往会在脑海中勾勒出一个机器人&#xff1a;一个可靠的管家&#xff0c;或是一个可怕的终结者&#xff0c;这取决于你问的是谁。但是机器学习并不是未来的幻想&#xff0c;它已经…

【吃透Java手写】3-SpringBoot-简易版-源码解析

【吃透Java手写】SpringBoot-简易版-源码解析 1 SpringbootDemo2 准备工作2.1 Springboot-my2.1.1 依赖2.1.2 SpringBootApplication2.1.3 SJBSpringApplication2.1.3.1 run方法 2.2 Springboot-user2.2.1 依赖2.2.2 UserController2.2.3 UserApplication 2.3 分析run方法的逻辑…

第二章 checkpoint机制 - 介绍

Checkpoint介绍 1、介绍 PostgreSQL基于DRAMHDD/SSD两层存储架构&#xff0c;所有读写都在DRAM中进行。由于数据写大部分都是随机的&#xff0c;为提高数据库性能&#xff0c;通过写前日志WAL将所有修改都记录到日志中&#xff0c;事务提交时&#xff0c;将日志持久化到磁盘即…

Java入门基础学习笔记12——变量详解

变量详解&#xff1a; 变量里的数据在计算机中的存储原理。 二进制&#xff1a; 只有0和1&#xff0c; 按照逢2进1的方式表示数据。 十进制转二进制的算法&#xff1a; 除二取余法。 6是110 13是1101 计算机中表示数据的最小单元&#xff1a;一个字节&#xff08;byte&…

通俗的理解网关的概念的用途(一)

网关这个概念最早使用于网络&#xff0c;但在当今的智能设备/产品界中&#xff0c;硬生生的被产品人也搞出来一个“网关”的概念&#xff0c;这让早期的咱们这些只知道网络中的网关的人&#xff0c;听得稀里糊涂的。比如智能门锁、安防摄像头等&#xff0c;在产品的使用和介绍中…

java JMH 学习

JMH 是什么&#xff1f; JMH&#xff08;Java Microbenchmark Harness&#xff09;是一款专用于代码微基准测试的工具集&#xff0c;其主要聚焦于方法层面的基准测试&#xff0c;精度可达纳秒级别。此工具由 Oracle 内部负责实现 JIT 的杰出人士编写&#xff0c;他们对 JIT 及…

服务号转订阅号的操作步骤(吐血整理)

服务号和订阅号有什么区别&#xff1f;服务号转为订阅号有哪些作用&#xff1f;我们知道&#xff0c;公众号分为服务号和订阅号两种&#xff0c;服务号只能企业才可以申请&#xff0c;订阅号是企业和个人都可以申请。其中最大的区别是服务号一个月只能发送4次群发&#xff0c;但…

shopro商城 源码搭建/部署/上线/运营/售后/更新

基于Fastadmin和Uniapp进行开发的多平台&#xff08;微信公众号、微信小程序、H5网页、Android-App、IOS-App&#xff09;购物商城&#xff0c;拥有强大的店铺装修、自定义模板、路由同步、多端支付&#xff08;微信&#xff0c;支付宝&#xff09;、多规格商品、运费模板、多地…

我在洛杉矶采访到了亚马逊云全球首席信息官CISO(L11)!

在本次洛杉矶举办的亚马逊云Re:Inforce全球安全大会中&#xff0c;小李哥作为亚马逊大中华区开发者社区和自媒体代表&#xff0c;跟着亚马逊云安全产品团队采访了亚马逊云首席信息安全官(CISO)CJ Moses、亚马逊副总裁Eric Brandwine和亚马逊云首席高级安全工程师Becky Weiss。 …

【学习AI-相关路程-工具使用-自我学习-Ubuntucudavisco-开发工具尝试-基础样例 (2)】

【学习AI-相关路程-工具使用-自我学习-cuda&visco-开发工具尝试-基础样例 &#xff08;2&#xff09;】 1、前言2、环境说明3、总结说明4、工具安装0、验证cuda1、软件下载2、插件安装 5、软件设置与编程练习1、创建目录2、编译软件进入目录&创建两个文件3、编写配置文…

可微分矢量图形光栅化用于编辑和学习

图1. 我们引入了一种通过反向传播将光栅和矢量域联系起来的矢量图形可微分光栅化器。可微分光栅化实现了许多新颖的矢量图形应用。&#xff08;a&#xff09;在几何约束下&#xff0c;通过局部优化图像空间度量&#xff08;如不透明度&#xff09;来实现交互式编辑。&#xff0…

如何使用vue脚手架创建项目

前言 使用vue搭建项目的时候&#xff0c;我们可以通过对应的cmd命令去打开脚手架&#xff0c;然后自己配置对应的功能插件 说明&#xff1a; 要使用Vue脚手架创建项目&#xff0c;你需要先确保你已经安装了Node.js和npm&#xff08;Node.js的包管理器&#xff09;。然后&#…

uniapp 版本检查更新

总体来说uniapp的跨平台还是很不错的&#xff0c;虽然里面各种坑要去踩&#xff0c;但是踩坑也是开发人员的必修课和成长路。 这不&#xff0c;今天就来研究了一下版本检查更新就踩到坑了。。。先来看看检查更新及下载、安装的实现。 先来看看页面&#xff1a; 从左到右依次为…

CSRF、XSS攻防原理及解决方案

一、CSRF CSRF 全称叫做&#xff0c;跨站请求伪造(Cross—Site Request Forgery)&#xff0c;顾名思义&#xff0c;攻击者盗用了你的身份&#xff0c;以你的名义发送恶意请求&#xff0c;对服务器来说这个请求是完全合法的&#xff0c;但是却完成了攻击者所期望的一个操作&…

bbr 是真不行

bbr 作为 mimd 实例如何收敛到公平请看 瓶颈带宽的公平收敛&#xff0c;但这只是公平收敛&#xff0c;并不是 buffer 收敛。 上午跟朋友讨论了一个有趣的问题&#xff0c;感觉有必要揭露一下 bbr 的 buffer 不收敛。若不是有 probertt&#xff0c;多流共享瓶颈链路场景下&…

TC377TX 超声波雷达数据更新缓慢问题排查

1、问题表象 通过标定数据查看超声波雷达实时的距离大小,发现距离并没有实时更新,而是在实际值与默认值之间跳变,更新十分缓慢。   泊车功能必须依赖超声波雷达测距来实现,当雷达数据更新缓慢时,会导致泊车失败。 2、超声波雷达测距实现原理 MCU给超声波雷达发送一个40…

【SpringBoot整合系列】SpringBoot整合RabbitMQ-消息可靠性

目录 确保消息的可靠性RabbitMQ 消息发送可靠性分析解决方案开启事务机制发送方确认机制单条消息处理消息批量处理 失败重试自带重试机制业务重试 RabbitMQ 消息消费可靠性如何保证消息在队列RabbitMQ 的消息消费&#xff0c;整体上来说有两种不同的思路&#xff1a;确保消费成…

Python专题:十、字典(1)

数据类型:字典,是一个集合性质的数据类型 字典的初始化 字典{关键字:数值} 新增元素 修改元素 字典元素访问 字典[关键字} in 操作符 字典关键字检测 字典元素遍历 ①遍历关键字

ESP32引脚入门指南(六):从理论到实践(UART)

ESP32开发板具有UART0、UART1和UART2三个UART接口&#xff0c;支持异步通信(RS232和RS485)和IrDA速率高达5mbps。这些接口提供了丰富的串行通信选项&#xff0c;允许与各种设备进行全双工通信。 UART接口概述与引脚配置 UART 是一种全双工通信协议&#xff0c;允许数据同时在…