Java通過百度地圖API獲取定位(普通IP定位)的方法教程
項目中有一個登錄郵箱提醒的功能,需要根據(jù)IP地址獲取定位信息,從而更好地提示用戶賬號登錄的所在地。為此,花費了一些時間來實現(xiàn)這個功能。
搜索了一下,發(fā)現(xiàn)關(guān)于獲取定位的文章說明都不夠詳細,于是決定自己創(chuàng)作一篇文章,希望能夠幫助到有需求的小伙伴~
因為博主日常生活中用的導(dǎo)航APP就是百度地圖,所以使用百度地圖的API來實現(xiàn)這個功能。
百度地圖開放平臺
本篇文章都是圍繞百度地圖的開放平臺官網(wǎng)的相關(guān)說明來展開的,訪問下面的鏈接
百度地圖開放平臺 | 百度地圖API SDK | 地圖開發(fā) 這是開放平臺的首頁截圖

開始前的準(zhǔn)備工作
點擊上方導(dǎo)航菜單的開發(fā)文檔-Web服務(wù)API總覽

緊接著,點擊左側(cè)菜單中的定位,點擊普通IP定位

然后根據(jù)開發(fā)文檔的提示完成步驟1、2、3

學(xué)習(xí)官網(wǎng)API文檔
最后點擊步驟4,開始使用百度地圖的API

如上圖,文檔已經(jīng)給出了API的接口地址和參數(shù)說明,以及API接口返回的參數(shù)格式。
{
"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配置
在這里,需要修改一下創(chuàng)建的應(yīng)用的相關(guān)設(shè)置。

點擊上圖的設(shè)置按鈕來到這個頁面,然后拉到頁面的底部,修改應(yīng)用的請求校驗方式為sn校驗方式,然后點擊提交按鈕。

把AK復(fù)制到示例代碼的輸入框中,點擊確認按鈕自動生成獲取定位的Java代碼,可以說非常方便。

Java代碼獲取定位
通過官網(wǎng)生成代碼
新建一個類SearchHttpAK,把示例代碼復(fù)制到SearchHttpAK類里,復(fù)制按鈕在下圖紅框內(nèi)。

調(diào)整之后的代碼如下(真實的AK和SK都已經(jīng)被博主替換了,這里的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校驗:
* 根據(jù)您選擇的AK已為您生成調(diào)用代碼
* 檢測您當(dāng)前的AK設(shè)置了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 自帶的轉(zhuǎn)碼方式 第二種方式使用的 spring 的轉(zhuǎn)碼方法 兩種均可
// 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跟參數(shù)對出現(xiàn)順序有關(guān),get請求請使用LinkedHashMap保存<key,value>,該方法根據(jù)key的插入順序排序;post請使用TreeMap保存<key,value>,該方法會自動將key按照字母a-z順序排序。
// 所以get請求可自定義參數(shù)順序(sn參數(shù)必須在最后)發(fā)送請求,但是post請求必須按照字母a-z順序填充body(sn參數(shù)必須在最后)。
// 以get請求為例:http://api.map.baidu.com/geocoder/v2/?address=百度大廈&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入順序必須跟get請求中對應(yīng)參數(shù)的出現(xiàn)順序保持一致。
Map<String, String> paramsMap = new LinkedHashMap<>(3);
paramsMap.put("ip", "111.206.214.37");
paramsMap.put("coor", "bd09ll");
paramsMap.put("ak", AK);
// 調(diào)用下面的toQueryString方法,對LinkedHashMap內(nèi)所有value作utf8編碼,拼接返回結(jié)果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");
// 調(diào)用下面的MD5方法得到最后的sn簽名
String sn = snCal.MD5(tempStr);
System.out.println(sn);
return sn;
}
// 對Map內(nèi)所有value作utf8編碼,拼接返回結(jié)果
public String toQueryString(Map<?, ?> data) {
StringBuilder queryString = new StringBuilder();
for (Map.Entry<?, ?> pair : data.entrySet()) {
queryString.append(pair.getKey()).append("=");
// 第一種方式使用的 jdk 自帶的轉(zhuǎn)碼方式 第二種方式使用的 spring 的轉(zhuǎn)碼方法 兩種均可
// 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計算方法,調(diào)用了MessageDigest庫函數(shù),并把byte數(shù)組結(jié)果轉(zhuǎn)換成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());運行生成的代碼
然后運行一下代碼,如果能看到下面這樣的運行結(jié)果,恭喜你,你已經(jīng)成功了一大半~

不要糾結(jié)獲取到的位置信息里很多16進制,因為馬上就要把他轉(zhuǎn)成一個自定義的實體類
創(chuàng)建接口返回對象
根據(jù)這個API返回的JSON格式字符串的結(jié)構(gòu),創(chuàng)建4個對應(yīng)的實體類
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字符串轉(zhuǎn)成Location對象
修改一下部分方法的名稱,然后把字符串通過fastjson的API轉(zhuǎn)成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校驗:
* 根據(jù)您選擇的AK已為您生成調(diào)用代碼
* 檢測您當(dāng)前的AK設(shè)置了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 自帶的轉(zhuǎn)碼方式 第二種方式使用的 spring 的轉(zhuǎn)碼方法 兩種均可
// 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跟參數(shù)對出現(xiàn)順序有關(guān),get請求請使用LinkedHashMap保存<key,value>,該方法根據(jù)key的插入順序排序;post請使用TreeMap保存<key,value>,該方法會自動將key按照字母a-z順序排序。
// 所以get請求可自定義參數(shù)順序(sn參數(shù)必須在最后)發(fā)送請求,但是post請求必須按照字母a-z順序填充body(sn參數(shù)必須在最后)。
// 以get請求為例:http://api.map.baidu.com/geocoder/v2/?address=百度大廈&output=json&ak=yourak,paramsMap中先放入address,再放output,然后放ak,放入順序必須跟get請求中對應(yīng)參數(shù)的出現(xiàn)順序保持一致。
Map<String, String> paramsMap = new LinkedHashMap<>(3);
paramsMap.put("ip", "111.206.214.37");
paramsMap.put("coor", "bd09ll");
paramsMap.put("ak", AK);
// 調(diào)用下面的toQueryString方法,對LinkedHashMap內(nèi)所有value作utf8編碼,拼接返回結(jié)果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");
// 調(diào)用下面的MD5方法得到最后的sn簽名
return MD5(tempStr);
}
// 對Map內(nèi)所有value作utf8編碼,拼接返回結(jié)果
public static String toQueryString(Map<?, ?> data) {
StringBuilder queryString = new StringBuilder();
for (Map.Entry<?, ?> pair : data.entrySet()) {
queryString.append(pair.getKey()).append("=");
// 第一種方式使用的 jdk 自帶的轉(zhuǎn)碼方式 第二種方式使用的 spring 的轉(zhuǎn)碼方法 兩種均可
// 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計算方法,調(diào)用了MessageDigest庫函數(shù),并把byte數(shù)組結(jié)果轉(zhuǎn)換成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地址即可獲取到定位信息~
代碼的最后優(yōu)化
上面的代碼已經(jīng)是進行了一定的優(yōu)化,除此之外,可以把AK和SK配置到application.yml中,可以動態(tài)地修改。最后重命名一下這個類,改成類似LocationUtils這樣的名字。
總結(jié)
到此這篇關(guān)于Java通過百度地圖API獲取定位(普通IP定位)的文章就介紹到這了,更多相關(guān)Java百度地圖API獲取定位內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運行的操作步驟
這篇文章主要介紹了Windows10系統(tǒng)下修改jar中的文件并重新打包成jar文件然后運行的操作步驟,文中通過圖文結(jié)合的形式給大家講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-08-08
springboot網(wǎng)站應(yīng)用使用第三方qq登錄的實現(xiàn)過程
這篇文章主要介紹了springboot網(wǎng)站應(yīng)用使用第三方qq登錄,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-09-09
詳解spring cloud整合Swagger2構(gòu)建RESTful服務(wù)的APIs
這篇文章主要介紹了詳解spring cloud整合Swagger2構(gòu)建RESTful服務(wù)的APIs,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
java中HashMap.values()轉(zhuǎn)為ArrayList()問題
這篇文章主要介紹了java中HashMap.values()轉(zhuǎn)為ArrayList()問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03
Mybatis實現(xiàn)關(guān)聯(lián)關(guān)系映射的方法示例
本文主要介紹了Mybatis實現(xiàn)關(guān)聯(lián)關(guān)系映射的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
并行Stream與Spring事務(wù)相遇會發(fā)生什么?
這篇文章主要介紹了并行Stream與Spring事務(wù)相遇會發(fā)生什么?文章主要解決實戰(zhàn)中的Bug及解決方案和技術(shù)延伸,具有一定的參考價值,需要的小伙伴可以參考一下2022-05-05

