基于SpringBoot+WebSocket实现地图上绘制车辆实时运动轨迹图
实现基于北斗卫星的车辆定位和轨迹图的Maven工程(使用模拟数据),我们将使用以下技术:
- Spring Boot:作为后端框架,用来提供数据接口。
- Thymeleaf:作为前端模板引擎,呈现网页。
- Leaflet.js:一个开源的JavaScript库,用于显示交互式地图。
- Simulated Data:使用随机生成的模拟GPS数据来模拟北斗卫星车辆位置。
- WebSocket:用于实现实时数据推送,确保地图位置每秒更新。
目录
1. 项目结构
2. Maven依赖配置 (pom.xml)
3. 实现后端服务
3.1 BeidouApplication.java
4. 配置文件 (application.properties)
5. 启动项目
6. 访问页面
1. 项目结构
创建一个Maven项目,基本结构如下:
项目结构图:
2. Maven依赖配置 (pom.xml)
首先在pom.xml
中添加必要的依赖,确保使用Spring Boot、WebSocket和Thymeleaf:
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf for rendering HTML -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- WebSocket for real-time communication -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- Lombok (Optional, for cleaner code) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
3. 实现后端服务
3.1 BeidouApplication.java
这是Spring Boot的启动类:
package com.example.beidou;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BeidouApplication {
public static void main(String[] args) {
SpringApplication.run(BeidouApplication.class, args);
}
}
4. 配置文件 (application.properties)
server.port=8080
5. 启动项目
确保你有Java和Maven环境,在项目根目录执行以下命令启动应用:
mvn spring-boot:run
6. 访问页面
在浏览器中访问 http://localhost:8080
,你应该可以看到一个地图,显示车辆的实时位置和轨迹更新。
效果图:
Controller:
package com.example.beidou.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @RestController public class VehicleController { private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); @Autowired private SimpMessagingTemplate messagingTemplate; private Map<String, Map<String, Double>> vehiclePositions = new HashMap<String, Map<String, Double>>() {{ put("Vehicle 1", new HashMap<String, Double>() {{ put("latitude", 39.9042);//北京 put("longitude", 116.4074); }}); put("Vehicle 2", new HashMap<String, Double>() {{ put("latitude", 31.2304);//上海 put("longitude", 121.4737); }}); put("Vehicle 3", new HashMap<String, Double>() {{ put("latitude", 22.3964);// 香港 put("longitude", 114.1095); }}); put("Vehicle 4", new HashMap<String, Double>() {{ put("latitude", 30.5728);//成都 put("longitude", 104.0668); }}); put("Vehicle 5", new HashMap<String, Double>() {{ put("latitude", 34.3416);// 西安 put("longitude", 108.9398); }}); }}; private Map<String, Map<String, Double>> vehicleTargets = new HashMap<String, Map<String, Double>>() {{ put("Vehicle 1", new HashMap<String, Double>() {{ put("latitude", 31.2304);//上海 put("longitude", 121.4737); }}); put("Vehicle 2", new HashMap<String, Double>() {{ put("latitude", 39.9042);//北京 put("longitude", 116.4074); }}); put("Vehicle 3", new HashMap<String, Double>() {{ put("latitude", 34.3416);// 西安 put("longitude", 108.9398); }}); put("Vehicle 4", new HashMap<String, Double>() {{ put("latitude", 22.3964);// 香港 put("longitude", 114.1095); }}); put("Vehicle 5", new HashMap<String, Double>() {{ put("latitude", 30.5728);//成都 put("longitude", 104.0668); }}); }}; @GetMapping("/startSimulation") public String startSimulation() { executorService.scheduleAtFixedRate(this::sendVehicleUpdates, 0, 500, TimeUnit.MILLISECONDS); return "Simulation started!"; } @GetMapping("/stopSimulation") public String stopSimulation() { executorService.shutdownNow(); return "Simulation stopped!"; } private void sendVehicleUpdates() { Map<String, Map<String, Double>> updatedPositions = new HashMap<>(); for (Map.Entry<String, Map<String, Double>> entry : vehiclePositions.entrySet()) { String vehicleId = entry.getKey(); Map<String, Double> position = entry.getValue(); Map<String, Double> target = vehicleTargets.get(vehicleId); // 按一定速度向目标移动 double latDiff = target.get("latitude") - position.get("latitude"); double lonDiff = target.get("longitude") - position.get("longitude"); // 每次移动经纬度的 1/100 double newLatitude = position.get("latitude") + latDiff * 0.02; double newLongitude = position.get("longitude") + lonDiff * 0.02; position.put("latitude", newLatitude); position.put("longitude", newLongitude); updatedPositions.put(vehicleId, new HashMap<>(position)); } messagingTemplate.convertAndSend("/topic/vehicleLocation", updatedPositions); } }
WebSocketConfig:package com.example.beidou.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/vehicle-location").setAllowedOriginPatterns("*").withSockJS(); } }
前端页面代码有需要的,请私信我,有偿提供代码,白嫖党勿扰!