本文實戰接入高德地圖雲圖 API,實現服務人員位置雲端存儲 (App 端上報)、Servlet 端條件檢索 (按類型/城市/關鍵字)、球面距離計算 (經緯度轉米級距離),附完整建表、上傳、檢索、計算代碼與常見坑點。
_id、_location (經緯度)、_name、_address 等,支援自定義欄位並建立篩選索引。/v3/datamanage/data/create)。/v3/datasearch/...)。_id、_location、_name...),新增業務欄位:type (服務類型:按摩師/護理師)、user_id (關聯業務用戶 ID)。type 為篩選索引 (支援 filter=type:按摩師)。@WebServlet("/api/provider/search")
public class ProviderSearchServlet extends HttpServlet {
private static final String SEARCH_URL = "https://yuntuapi.amap.com/datasearch/around";
private static final String KEY = "你的Web服務Key";
private static final String TABLE_ID = "你的TableID";
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 1. 參數:經度,緯度,半徑(米),類型,分頁
String location = req.getParameter("location"); // "116.39,39.90"
int radius = Integer.parseInt(req.getParameter("radius")); // 5000
String type = req.getParameter("type"); // "按摩師"
int page = Integer.parseInt(req.getParameter("page")); // 1
int pageSize = Integer.parseInt(req.getParameter("page_size")); // 20
// 2. 組裝請求
String param = "key=" + KEY
+ "&tableid=" + TABLE_ID
+ "¢er=" + location
+ "&radius=" + radius
+ "&filter=type:" + URLEncoder.encode(type, "UTF-8")
+ "&page=" + page
+ "&pagesize=" + pageSize;
// 3. 發送 GET (HttpClient/OkHttp/HttpURLConnection 均可)
String json = HttpUtil.get(SEARCH_URL + "?" + param);
// 4. 直接透傳或解析後回傳
resp.setContentType("application/json;charset=UTF-8");
resp.getWriter().write(json);
}
}
public class GeoUtil {
private static final double EARTH_RADIUS = 6371000; // 米
/** 計算兩點球面距離 (米) */
public static double distance(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return EARTH_RADIUS * c;
}
/** 批次計算並按距離排序 */
public static List<ProviderDTO> sortByDistance(double userLat, double userLon,
List<ProviderDTO> providers) {
providers.forEach(p -> p.setDistance(distance(userLat, userLon, p.getLat(), p.getLon())));
providers.sort(Comparator.comparingDouble(ProviderDTO::getDistance));
return providers;
}
}
// Android/iOS SDK 同理,這裡用 HTTP 示範
public void updateLocation(String userId, double lat, double lon, String type) {
String url = "https://yuntuapi.amap.com/datamanage/data/create";
String param = "key=" + APP_KEY // Android/iOS Key
+ "&tableid=" + TABLE_ID
+ "&data={\"_location\":\"" + lon + "," + lat + "\","
+ "\"_name\":\"provider_" + userId + "\","
+ "\"type\":\"" + type + "\","
+ "\"user_id\":\"" + userId + "\"}";
HttpUtil.post(url, param); // 非阻塞異步發送
}
lng,lat),別搞反。filter 欄位 (如 type) 必須在控制台設為篩選索引,否則全表掃描極慢。count 總數,前端分頁用;單次最大 100 條。ST_Distance_Sphere 或 PostgreSQL PostGIS 推算到 DB 層。高德雲圖以「Table 存儲 + 篩選索引 + 多模式檢索 + 球面距離」四大能力,快速實現 LBS 業務。掌握 Key 隔離、經緯度順序、索引建立、坐標系統一、異步上報、距離計算下推 六大工程細節,即可構建穩定高效的位置服務後端。