2025-07-16
Spring Boot
0

目录

基于SpringBoot和高德地图API的最短路径规划实现
前言
一、准备工作
1. 注册高德开发者账号
2. 创建SpringBoot项目
二、实现代码
1. 配置高德地图API Key
2. 创建DTO类
3. 创建服务类
4. 创建控制器
三、前端调用示例
四、高德地图显示路线
五、总结

基于SpringBoot和高德地图API的最短路径规划实现

前言

在现代Web应用中,基于位置的服务(LBS)变得越来越重要。本文将介绍如何使用SpringBoot框架结合高德地图API,实现基于用户当前位置的10个点位最短路径规划功能。这个功能可以广泛应用于物流配送、旅游路线规划等场景。

一、准备工作

1. 注册高德开发者账号

首先需要访问高德开放平台注册账号并创建应用,获取API Key。

2. 创建SpringBoot项目

使用Spring Initializr创建一个新的SpringBoot项目,添加以下依赖:

xml
<dependencies> <!-- Spring Boot Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- HTTP Client --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> <!-- JSON Processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> </dependencies>

二、实现代码

1. 配置高德地图API Key

application.properties中添加配置:

properties
amap.key=你的高德API Key amap.direction.url=https://restapi.amap.com/v3/direction/driving

2. 创建DTO类

java
import lombok.Data; @Data public class Location { private Double longitude; // 经度 private Double latitude;// 纬度 } @Data public class RouteRequest { private Location origin;// 起点 private List<Location> waypoints; // 途经点(最多10个) private Location destination;// 终点 } @Data public class RouteResponse { private String status;// 请求状态 private String info;// 返回信息 private String route;// 规划路径 private Integer distance;// 路径距离(米) private Integer duration;// 预计时间(秒) }

3. 创建服务类

java
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import com.fasterxml.jackson.databind.ObjectMapper; @Service public class AmapService { @Value("${amap.key}") private String apiKey; @Value("${amap.direction.url}") private String directionUrl; private final ObjectMapper objectMapper = new ObjectMapper(); public RouteResponse calculateShortestRoute(RouteRequest request) throws Exception { // 构建途经点字符串 String waypoints = request.getWaypoints().stream() .limit(10) // 限制最多10个途经点 .map(loc -> loc.getLongitude() + "," + loc.getLatitude()) .collect(Collectors.joining("|")); // 构建请求URL String url = String.format("%s?key=%s&origin=%s,%s&destination=%s,%s&waypoints=%s", directionUrl, apiKey, request.getOrigin().getLongitude(), request.getOrigin().getLatitude(), request.getDestination().getLongitude(), request.getDestination().getLatitude(), waypoints); // 发送HTTP请求 try (CloseableHttpClient client = HttpClients.createDefault()) { HttpGet httpGet = new HttpGet(url); String response = EntityUtils.toString(client.execute(httpGet).getEntity()); // 解析响应 return parseResponse(response); } } private RouteResponse parseResponse(String json) throws Exception { // 这里简化处理,实际应根据高德API返回的JSON结构进行完整解析 Map<String, Object> map = objectMapper.readValue(json, Map.class); RouteResponse response = new RouteResponse(); response.setStatus(map.get("status").toString()); response.setInfo(map.get("info").toString()); if ("1".equals(response.getStatus())) { Map<String, Object> route = (Map<String, Object>) ((List<Object>) map.get("route")).get(0); Map<String, Object> path = (Map<String, Object>) ((List<Object>) route.get("paths")).get(0); response.setRoute(path.get("steps").toString()); response.setDistance(Integer.parseInt(path.get("distance").toString())); response.setDuration(Integer.parseInt(path.get("duration").toString())); } return response; } }

4. 创建控制器

java
import org.springframework.web.bind.annotation.*; import org.springframework.beans.factory.annotation.Autowired; @RestController @RequestMapping("/api/route") public class RouteController { @Autowired private AmapService amapService; @PostMapping("/shortest") public RouteResponse getShortestRoute(@RequestBody RouteRequest request) { try { return amapService.calculateShortestRoute(request); } catch (Exception e) { RouteResponse response = new RouteResponse(); response.setStatus("0"); response.setInfo("路径规划失败: " + e.getMessage()); return response; } } }

三、前端调用示例

html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>最短路径规划</title> <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> </head> <body> <h1>最短路径规划</h1> <button onclick="getCurrentLocation()">获取当前位置并规划路线</button> <div id="result"></div> <script> function getCurrentLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( position => { const currentLoc = { longitude: position.coords.longitude, latitude: position.coords.latitude }; planRoute(currentLoc); }, error => { alert('获取位置失败: ' + error.message); } ); } else { alert('您的浏览器不支持地理位置功能'); } } function planRoute(currentLoc) { // 模拟10个途经点(实际应用中可以从数据库获取) const waypoints = [ {longitude: 116.481028, latitude: 39.989643}, {longitude: 116.434436, latitude: 39.90816}, {longitude: 116.416351, latitude: 39.981597}, {longitude: 116.340581, latitude: 39.940474}, {longitude: 116.399028, latitude: 39.915149}, {longitude: 116.374302, latitude: 39.978858}, {longitude: 116.387271, latitude: 39.939577}, {longitude: 116.425002, latitude: 39.914171}, {longitude: 116.353165, latitude: 39.966896}, {longitude: 116.412222, latitude: 39.957408} ]; // 设置终点(这里设为最后一个途经点) const destination = waypoints[waypoints.length - 1]; const request = { origin: currentLoc, waypoints: waypoints, destination: destination }; axios.post('/api/route/shortest', request) .then(response => { const result = response.data; let html = `<h2>规划结果</h2>`; if (result.status === '1') { html += `<p>距离: ${result.distance}米</p>`; html += `<p>预计时间: ${Math.round(result.duration/60)}分钟</p>`; html += `<p>路线详情: ${result.route}</p>`; } else { html += `<p style="color:red">${result.info}</p>`; } document.getElementById('result').innerHTML = html; }) .catch(error => { document.getElementById('result').innerHTML = `<p style="color:red">请求失败: ${error.message}</p>`; }); } </script> </body> </html>

四、高德地图显示路线

为了更直观地显示路线,可以在前端集成高德地图JavaScript API:

html
<div id="map-container" style="width: 800px; height: 600px;"></div> <script src="https://webapi.amap.com/maps?v=2.0&key=你的高德JS API Key"></script> <script> let map; function initMap() { map = new AMap.Map('map-container', { zoom: 12, center: [116.397428, 39.90923] }); } // 在planRoute函数中添加地图显示 function planRoute(currentLoc) { // ...之前的代码... axios.post('/api/route/shortest', request) .then(response => { const result = response.data; // ...之前的显示代码... if (result.status === '1') { // 清除旧路线 map.clearMap(); // 添加起点标记 new AMap.Marker({ position: [currentLoc.longitude, currentLoc.latitude], map: map, title: '起点' }); // 添加途经点标记 waypoints.forEach((point, index) => { new AMap.Marker({ position: [point.longitude, point.latitude], map: map, title: `途经点${index + 1}` }); }); // 添加终点标记 new AMap.Marker({ position: [destination.longitude, destination.latitude], map: map, title: '终点' }); // 绘制路线(简化处理,实际应使用返回的路线坐标) const path = [ [currentLoc.longitude, currentLoc.latitude], ...waypoints.map(p => [p.longitude, p.latitude]), [destination.longitude, destination.latitude] ]; new AMap.Polyline({ path: path, isOutline: true, outlineColor: '#ffeeff', borderWeight: 1, strokeColor: '#3366FF', strokeOpacity: 1, strokeWeight: 6, lineJoin: 'round', map: map }); // 调整视野显示所有标记 map.setFitView(); } }) // ...错误处理... } // 初始化地图 initMap(); </script>

五、总结

本文介绍了如何使用SpringBoot结合高德地图API实现基于当前位置的10个点位最短路径规划功能。关键点包括:

  1. 高德地图API的调用和响应解析
  2. SpringBoot后端服务的搭建
  3. 前端地理位置获取和地图展示
  4. 路径规划结果的展示

实际应用中,你可能还需要考虑:

  • 更完善的错误处理和日志记录
  • 对高德API返回数据的完整解析
  • 路径规划的优化算法
  • 用户认证和权限控制
  • 性能优化和缓存策略

如果想自定义算法实现最短路径规划,使用Dijkstra算法实现

希望本文能为你实现基于位置的服务提供有价值的参考。