简介这是一份面向Java后端开发者与小程序入门者的实战型项目源码围绕小程序地图定位场景演示如何用Java服务端配合前端完成位置服务。内容涉及GPS与网络定位、地理编码与反地理编码、路径规划、位置实时更新、隐私安全处理及前后端接口设计等关键环节适合希望打通地图API集成与位置数据处理的初中级开发者参考。压缩包共38个文件约314KB以15个png界面截图与图标、6个js逻辑脚本、5个wxss样式、4个wxml页面结构、4个json配置为主另含说明文档与开源协议目录涵盖location、index、logs等页面模块及utils工具类结构清晰便于按模块阅读。目前已有155人学习下载。通过这份源码读者可对照完整目录理解小程序页面组织与Java后端交互思路掌握地图定位从坐标获取到接口返回的落地流程并借鉴缓存优化与异常处理等实践细节。1. 从一份 Java 后端配小程序前端的定位包说起打开这个压缩包第一眼看到的不是 Java 源码而是一个标准的小程序前端目录pages/location、app.json、app.js、utils/util.js外加一堆locate.png、arrowright.png、play.png这类地图交互图标。很多人冲着「java 小程序 地图定位」这个关键词下载解压后却愣住——Java 在哪其实这正是当前主流做法小程序端负责采集经纬度、渲染地图、响应用户手势Java 后端负责接收坐标、做地理编码/反地理编码、路径规划、把结果回吐给前端。这份资源的价值不在于它用了多新的框架而在于它把「小程序地图定位」这条链路的前端骨架完整摆出来了配合 Java 服务端就能跑通一个可用的位置服务。适合正在做微信小程序项目实例、需要快速搭出定位页面的开发者也适合想理解前后端如何交换位置数据的 Java 后端。2. 拆开目录看定位链路前端骨架与 Java 后端的职责边界2.1 目录结构里藏着什么把 zip 解压后根目录下大致是这些内容路径类型作用pages/location/目录定位主页面含 wxml/wxss/js/jsonpages/index/目录入口页通常放跳转按钮pages/logs/目录日志页调试期看定位回调utils/util.js文件时间格式化、坐标处理等公共函数app.json文件全局页面注册、窗口样式、权限声明app.js文件小程序生命周期、全局数据image/目录地图控件图标定位、箭头、播放、暂停、垃圾桶package.json文件依赖描述通常很轻README.md文件使用说明LICENSE文件开源协议注意image目录里出现了locate.png、locateHL.png、arrowright.png、play.png、pause.png、trash.png、plus.png、stop.png、record.png。这套图标组合说明定位页不只是显示一个蓝点还包含轨迹记录、回放、清除轨迹这些操作。也就是说这份资源的目标场景是「带轨迹记录的定位小程序」而不是单纯查一下当前位置。2.2 为什么 Java 在后端而不是在小程序里小程序运行在微信容器内能直接调用的只有wx.getLocation、wx.openLocation、wx.chooseLocation这类原生 API以及map组件。它没有 JVM跑不了 Java 代码。所以「基于 Java 开发」指的是服务端那一层小程序把latitude、longitude通过wx.request发给 Java 接口Java 再去调地图服务商的 Web 服务 API 做逆地理编码、路径规划、围栏判断最后把结构化结果返回。常见做法是 Java 侧用 Spring Boot 起一个 REST 服务引入地图厂商的 Java SDK 或直接 HTTP 调用其 Web API。比如逆地理编码前端只传坐标后端返回省市区、街道、附近 POI。这样做的好处是密钥不暴露在小程序包里坐标处理逻辑可复用后续换地图厂商只改后端。2.3 前端定位页面的最小实现pages/location/location.js里通常会有这样一段核心逻辑// pages/location/location.js Page({ data: { latitude: 39.909, longitude: 116.397, markers: [], polyline: [] }, onLoad() { this.getCurrentLocation(); }, getCurrentLocation() { wx.getLocation({ type: gcj02, // 小程序地图组件要求 gcj02不能用 wgs84 success: (res) { const { latitude, longitude } res; this.setData({ latitude, longitude, markers: [{ id: 1, latitude, longitude, iconPath: /image/locate.png, width: 32, height: 32 }] }); this.reportToJava(latitude, longitude); }, fail: (err) { console.error(定位失败, err); wx.showToast({ title: 请检查定位权限, icon: none }); } }); }, reportToJava(lat, lng) { wx.request({ url: https://your-java-host/api/location/reverse, method: POST, data: { latitude: lat, longitude: lng }, success: (res) { console.log(Java 返回地址, res.data); } }); } });这段代码的逻辑说明wx.getLocation的type参数必须选gcj02因为小程序map组件和wx.openLocation都基于国测局坐标系传wgs84会出现几百米偏移这是最常见的翻车点。reportToJava把坐标 POST 给 Java 服务Java 侧再做逆地理编码。参数上latitude、longitude是浮点数精度保留 6 位小数足够。2.4 Java 后端接口的对应写法Java 侧接收坐标并调用地图 Web API常见写法如下// LocationController.java RestController RequestMapping(/api/location) public class LocationController { Value(${amap.key}) private String amapKey; PostMapping(/reverse) public MapString, Object reverse(RequestBody MapString, Object body) { double lat Double.parseDouble(body.get(latitude).toString()); double lng Double.parseDouble(body.get(longitude).toString()); // 调用高德逆地理编码 Web API String url String.format( https://restapi.amap.com/v3/geocode/regeo?location%f,%fkey%s, lng, lat, amapKey); RestTemplate rt new RestTemplate(); String resp rt.getForObject(url, String.class); MapString, Object result new HashMap(); result.put(raw, resp); result.put(status, ok); return result; } }逻辑说明注意高德 Web API 的location参数顺序是「经度,纬度」而小程序返回的是latitude在前。这个顺序写反了不会报错但会定位到错误位置属于典型的黑匣子问题。amapKey放在配置文件里不要硬编码。参数上lat、lng用double接收避免精度丢失。3. 把定位跑起来权限、坐标系与轨迹记录的实操步骤3.1 app.json 里的权限声明不能漏小程序要调wx.getLocation必须在app.json里声明permission和requiredPrivateInfos{ pages: [pages/index/index, pages/location/location, pages/logs/logs], window: { navigationBarTitleText: 地图定位, navigationBarBackgroundColor: #ffffff }, permission: { scope.userLocation: { desc: 用于展示您当前位置和记录轨迹 } }, requiredPrivateInfos: [getLocation, chooseLocation] }逻辑说明scope.userLocation的desc会出现在授权弹窗里写清楚用途能提高用户同意率。requiredPrivateInfos是较新版本基础库的要求漏了会导致getLocation直接失败报「getLocation:fail the api need to be declared in the requiredPrivateInfos field」。参数上pages数组第一项必须是启动页。3.2 坐标系选型gcj02 与 wgs84 的差别坐标系来源适用场景偏移情况wgs84GPS 原始坐标国际地图、部分海外服务在国内地图上偏移 50-500 米gcj02国测局加密坐标微信小程序 map 组件、高德、腾讯国内地图正确bd09百度加密坐标百度地图与 gcj02 互转有固定算法小程序map组件、wx.openLocation、wx.chooseLocation全部使用 gcj02。所以wx.getLocation的type必须写gcj02。如果后端拿到的是 wgs84需要先转换再存库否则地图上显示的点会飘。常见做法是 Java 侧引入坐标转换工具类把 wgs84 转 gcj02 后再做逆地理编码。3.3 轨迹记录polyline 与定时上报image目录里的record.png、play.png、pause.png、stop.png说明这份资源支持轨迹记录与回放。实现思路是开启记录后用wx.startLocationUpdate监听位置变化把每次坐标 push 进数组同时更新map的polyline。// 轨迹记录核心 startRecord() { this.recordPoints []; wx.startLocationUpdate({ success: () { wx.onLocationChange((res) { this.recordPoints.push({ latitude: res.latitude, longitude: res.longitude }); this.setData({ polyline: [{ points: this.recordPoints, color: #1aad19, width: 4, arrowLine: true }] }); }); } }); }逻辑说明wx.startLocationUpdate需要在app.json的requiredPrivateInfos里加上startLocationUpdate。onLocationChange的回调频率由系统控制通常 1-3 秒一次不要在里面做重计算。polyline的points数组元素必须含latitude、longitudearrowLine为 true 时显示方向箭头对应arrowright.png的用途。3.4 Java 侧存储轨迹与回放接口轨迹点上报到 Java 后通常存进数据库回放时按时间排序返回// TrackController.java PostMapping(/track/save) public String saveTrack(RequestBody TrackDTO dto) { // dto 含 userId、points 列表、startTime、endTime trackService.save(dto); return ok; } GetMapping(/track/{userId}) public ListTrackPoint getTrack(PathVariable String userId) { return trackService.listByUser(userId); }逻辑说明TrackDTO里 points 建议用ListPoint每个 Point 含lat、lng、timestamp。存储时按 userId 和时间建索引回放查询才不会慢。参数上如果轨迹点很多前端回放要分页拉取不要一次全量返回。4. 定位不准、授权失败、坐标偏移排查清单与避坑记录4.1 现象地图上蓝点偏移几百米原因wx.getLocation的type传了wgs84或者 Java 侧把 gcj02 当 wgs84 又转了一次。解决统一全链路用 gcj02Java 侧只在必要时做一次转换转换函数单独写单元测试验证。4.2 现象getLocation:fail the api need to be declared原因app.json缺少requiredPrivateInfos声明或声明了但基础库版本过低。解决补上requiredPrivateInfos: [getLocation]并在开发者工具里把调试基础库调到较新版本。4.3 现象用户拒绝授权后再也弹不出授权框原因wx.getLocation首次拒绝后再次调用不会自动弹窗直接走 fail。解决在 fail 回调里判断errMsg是否含auth deny引导用户去wx.openSetting手动开启不要反复调getLocation。4.4 现象Java 逆地理编码返回空或报错原因高德/百度 Web API 的location参数顺序写反或 key 的域名白名单没配。解决确认参数是「经度,纬度」并在控制台把服务器出口 IP 加入白名单。这个坑很隐蔽因为接口不报参数错误只返回空结果。4.5 现象轨迹回放时 polyline 不显示原因points数组为空或坐标是字符串而非数字。解决push 时确保latitude、longitude是Number类型回放前先判断数组长度大于 1单点无法构成线。5. 进阶把定位结果缓存起来减少无效请求定位接口调用是有成本的不管是wx.getLocation的功耗还是 Java 侧调地图 Web API 的配额。我一般会在 Java 侧加一层缓存同一个用户 30 秒内的逆地理编码结果直接返回缓存坐标变化超过阈值才重新请求。// 简易缓存示例 private final MapString, CacheEntry cache new ConcurrentHashMap(); public String reverseWithCache(String userId, double lat, double lng) { String key userId; CacheEntry entry cache.get(key); long now System.currentTimeMillis(); if (entry ! null now - entry.time 30_000 Math.abs(entry.lat - lat) 0.0001 Math.abs(entry.lng - lng) 0.0001) { return entry.address; } String address callAmap(lat, lng); cache.put(key, new CacheEntry(lat, lng, address, now)); return address; }逻辑说明阈值0.0001约等于 10 米小于这个距离认为位置没变。缓存时间 30 秒是经验值太短没效果太长地址更新不及时。生产环境建议用 Redis 替代本地 Map并设置过期时间。验证缓存是否生效可以在 Java 侧打日志观察同一用户连续请求时callAmap的调用次数。如果次数明显下降说明缓存命中。另外小程序端也可以用wx.getStorageSync缓存上一次定位结果冷启动时先展示旧位置再刷新体验会好很多。从那以后我每次接定位需求都强制先确认三件事坐标系是不是 gcj02、requiredPrivateInfos有没有声明、Java 侧参数顺序对不对。这三步走完基本不会翻车。希望帮到你。本文还有配套的精品资源点击获取
