在開發地理位置相關服務時,常需根據用戶 IP 地址解析其大致地理坐標(經緯度)。百度地圖開放平台提供 IP 定位 API,支援以 HTTP GET 方式請求,回傳 JSON 格式坐標。本文提供一個可直接用於生產環境的 Java 工具方法,涵蓋請求構建、響應解析、異常處理與座標提取完整流程。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
/**
* 根據 IP 地址透過百度地圖 API 獲取經緯度(BD-09 坐標系)
*
* @param ip 目標 IP 地址,傳入 null 或空字串則定位當前伺服器公網 IP
* @return String[] 長度為 2 的陣列:[0]=經度, [1]=緯度;解析失敗回傳 null
* @throws IOException 網路通訊異常
*/
public static String[] getIPXY(String ip) throws IOException {
// 1. 參數預處理
final String ak = "你的百度AK"; // TODO: 從配置檔/環境變數讀取,勿硬編碼
if (ip == null || ip.isEmpty()) {
ip = ""; // 空值讓 API 自動偵測請求端公網 IP
}
// 2. 構建請求 URL(協議建議升級 HTTPS)
String apiUrl = String.format(
"https://api.map.baidu.com/location/ip?ak=%s&ip=%s&coor=bd09ll",
ak, ip
);
// 3. 發送請求並讀取響應
StringBuilder response = new StringBuilder();
try (InputStream inputStream = new URL(apiUrl).openStream();
InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(reader)) {
String line;
while ((line = bufferedReader.readLine()) != null) {
response.append(line);
}
}
String json = response.toString();
if (json == null || json.isEmpty()) {
return null;
}
// 4. 解析 JSON 提取坐標(採用簡易字串解析,生產環境建議用 Jackson/Gson)
// 範例響應:{"status":0,"content":{"point":{"x":"116.404","y":"39.915"},"address":"北京市"}}
int pointIndex = json.indexOf("\"point\"");
if (pointIndex == -1) {
return null; // 無 point 節點,可能 status != 0
}
int endIndex = json.indexOf("}}", pointIndex);
if (endIndex == -1) {
return null;
}
// 截取 point 物件片段:{"x":"116.404","y":"39.915"}
String pointJson = json.substring(pointIndex - 1, endIndex + 1); // 含前後大括號
// 簡易解析 x/y 值
String[] parts = pointJson.split("[:,]");
if (parts.length < 4) {
return null;
}
// parts 範例:["{\"point\"", "\"x\"", "\"116.404\"", "\"y\"", "\"39.915\"}"]
String x = parts[2].replaceAll("[\"]", "").trim();
String y = parts[4].replaceAll("[\"]", "").trim();
return new String[]{x, y};
}
coor=bd09ll:回傳 BD-09(百度加密)經緯度,可直接用於百度地圖 SDK/JS API 顯示coor=gcj02ll| status | 含義 | 處理建議 |
|---|---|---|
| 0 | 成功 | 正常解析坐標 |
| 1 | 內部錯誤 | 重試或聯繫百度支援 |
| 2 | 參數錯誤 | 檢查 AK、IP 格式 |
| 101 | AK 驗證失敗 | 確認 AK 正確性、白名單配置 |
| 102 | 服務未開通 | 控制台啟用 IP 定位服務 |
| 302 | 配額超限 | 提升配額或優化調用頻率 |
HttpClient 或 OkHttp 替代 URL.openStream(),設定連線/讀取超時CompletableFuture 或反應式框架非阻塞調用public class BaiduIpLocationDemo {
public static void main(String[] args) {
try {
// 測試指定 IP
String[] coords = getIPXY("220.181.38.148"); // 百度總部 IP
if (coords != null) {
System.out.printf("經度: %s, 緯度: %s%n", coords[0], coords[1]);
} else {
System.out.println("坐標解析失敗");
}
// 測試自動偵測當前機器公網 IP
String[] localCoords = getIPXY(null);
if (localCoords != null) {
System.out.printf("本機公網 IP 經度: %s, 緯度: %s%n", localCoords[0], localCoords[1]);
}
} catch (IOException e) {
System.err.println("網路請求異常: " + e.getMessage());
e.printStackTrace();
}
}
// 此處貼上上方 getIPXY 方法
}
百度 IP 定位 API 提供輕量級的 IP 轉坐標能力,適合「不需精準到門牌號、僅需城市/區級定位」的業務場景(如廣告投放、風控分析、內容分發)。生產環境接入時,請務必關注配額限制、AK 安全、超時重試、坐標系一致性四大核心要點,並建議封裝為獨立微服務或工具模組統一管理。