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ā) 這是開放平臺的首頁截圖
開始前的準備工作
點擊上方導(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)用代碼 * 檢測您當前的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)用代碼 * 檢測您當前的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-08springboot網(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-01java中HashMap.values()轉(zhuǎn)為ArrayList()問題
這篇文章主要介紹了java中HashMap.values()轉(zhuǎn)為ArrayList()問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03Mybatis實現(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