本文关键词:java geo point
做这行十二年,见过太多人在 geo point 这个问题上栽跟头。特别是刚入行那会儿,我也觉得这玩意儿简单,不就是经纬度嘛,存个数据库,查出来画个图完事。结果呢?客户骂娘,老板骂人,我也被骂得怀疑人生。今天不整那些虚头巴脑的理论,就聊聊我在项目里踩过的坑,以及怎么让 java geo point 的精度真正达标。
先说个真事。去年有个做同城配送的项目,客户反馈骑手位置漂移严重。有时候骑手明明在马路东边,地图上显示他在河里游泳。我查了半天代码,发现他们用的还是最原始的 WGS84 坐标直接入库。这里有个大坑,国内大部分地图服务商,比如高德、百度,用的都不是 WGS84。百度是 BD09,高德是 GCJ02。你拿 GPS 模块直接读出来的 WGS84 数据,不经转换直接丢给百度地图 API,偏差能大到几百米。这就是为什么你的 java geo point 看起来数据没错,但位置就是不对。
很多新手喜欢直接调 API 转换,但这在并发量大的时候,性能是个大问题。我现在的做法是,在 Java 层做批量转换。别一个个查,太慢。我写了一个工具类,利用数学公式在内存里直接算。虽然 GCJ02 的加偏算法是个黑盒,没有官方公开的精确公式,但网上有很多开源的实现,精度大概在 0.1 米左右,对于大多数业务场景完全够用。如果你需要极高精度,比如测绘级,那得花钱买专业的 SDK 或者服务,别想着免费白嫖。
再说说数据库设计。很多表里直接存两个字段,lat 和 lng。这没问题,但查询效率低。如果你要做附近的店、附近的人这种基于距离的查询,强烈建议引入 GeoHash 或者使用 PostGIS。PostGIS 是 PostgreSQL 的扩展,专门处理地理空间数据。它支持 GIST 索引,查询速度比你自己写 SQL 算距离快几个数量级。我有个客户,以前用 MySQL 查附近 5 公里的人,每次要 2 秒,换成 PostGIS 后,0.05 秒出结果。这体验差距,客户能满意。
还有个小细节,很多人忽略坐标系的类型定义。在 Java 实体类里,最好明确标注这个 geo point 是什么坐标系。比如加个注解 @CoordinateSystem("GCJ02")。这样后续维护的人一眼就知道这数据是哪来的,要不要转。不然接手的人以为是 WGS84,直接画到百度地图上,又得出一堆鬼畜数据。
另外,关于精度保留。别用 float,用 double。float 的精度不够,小数点后几位就丢了,导致定位点乱跳。我在代码里见过有人用 float 存经纬度,结果两个点距离很近,算出来距离却是负数,逻辑直接崩了。这属于低级错误,但真的有人犯。
最后,测试环节别偷懒。别只在本地测,要去真实环境。室内、地下室、高楼密集区,这些地方的 GPS 信号都弱,容易漂移。这时候光靠坐标转换没用,得结合基站定位或者 Wi-Fi 定位做融合。如果只依赖 GPS,那你的 java geo point 在室内基本就是摆设。
总结一下,搞 geo point 定位,核心就三点:坐标系转换要准,数据库索引要用对,测试场景要全。别怕麻烦,前期多花点时间把基础打牢,后期省下的都是真金白银。希望这些经验能帮大家在 java geo point 的开发路上少踩点坑,多拿点奖金。毕竟,定位准了,客户才肯掏钱,对吧?