完整图片效果:https://z3.ax1x.com/2021/11/03/IEEYuj.gif
项目POM配置实现使用SpringBoot(2.5.6)+WebSocket(2.5.6)
注册ServerEndpointExporter4.0.0 org.springframework.boot spring-boot-starter-parent2.5.6 cn.xiaoshuai wsapp0.0.1-SNAPSHOT wsapp wsapp Project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-websocketorg.springframework.boot spring-boot-devtoolsruntime true org.projectlombok lomboktrue org.springframework.boot spring-boot-starter-testtest com.alibaba fastjson1.2.60 cn.hutool hutool-all4.5.11 org.springframework.boot spring-boot-maven-pluginorg.projectlombok lombok
如果想在使用内嵌容器的Spring Boot应用中使用@ServerEndpoint,你需要声明一个单独的ServerEndpointExporter
@Bean
package cn.xiaoshuai.wsapp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
WebSocket端点创建ServerEndpoint
package cn.xiaoshuai.wsapp.ws.controller;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
@Slf4j
@ServerEndpoint(value = "/ws/serve/{clientId}")
@Component
public class MapWebSocket {
private Session session;
private static CopyOnWriteArraySet webSockets =new CopyOnWriteArraySet<>();
private static Map sessionPool = new HashMap();
@onOpen
public void onOpen(Session session, @PathParam(value="clientId")String clientId) {
Map map = new HashMap();
try {
this.session = session;
webSockets.add(this);
sessionPool.put(clientId, session);
log.info("【websocket消息】有新的连接,总数为:"+webSockets.size());
map.put("clientId",clientId);
map.put("msg","连接成功");
session.getAsyncRemote().sendText(JSON.toJSonString(map));
} catch (Exception e) {
map.put("msg","连接失败");
session.getAsyncRemote().sendText(JSON.toJSonString(map));
}
}
@onClose
public void onClose(@PathParam(value="clientId")String clientId) {
try {
webSockets.remove(this);
log.info("【websocket消息】连接断开,总数为:"+webSockets.size());
} catch (Exception e) {
}
}
@onMessage
public void onMessage(@PathParam(value="clientId")String clientId,String message) {
log.debug("【websocket消息】收到客户端消息:"+message);
Map obj = new HashMap();
//业务类型
obj.put("message", message);
//消息内容
obj.put("msgTxt", "客户端消息");
session.getAsyncRemote().sendText(JSON.toJSonString(obj));
}
public void sendAllMessage(String message) {
log.info("【websocket消息】广播消息:"+message);
for(MapWebSocket webSocket : webSockets) {
try {
if(webSocket.session.isOpen()) {
webSocket.session.getAsyncRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void sendoneMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public Map getSessionPool() {
return sessionPool;
}
public void sendMoreMessage(String[] userIds, String message) {
for(String userId:userIds) {
Session session = sessionPool.get(userId);
if (session != null&&session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:"+message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
编写一个模拟数据推送的Controller
package cn.xiaoshuai.wsapp.ws.controller;
import cn.hutool.core.util.RandomUtil;
import cn.xiaoshuai.wsapp.base.controller.ApiRestController;
import cn.xiaoshuai.wsapp.contants.CoordsListData;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.websocket.Session;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/deviceMonitor/socket")
@Slf4j
public class SendRestController extends ApiRestController {
@Autowired
private MapWebSocket mapWebSocket;
@PostMapping("/sends/{clientId}")
public void sendsMsg(@PathVariable("clientId") String clientId) throws Exception{
log.info("----->客户端个数{}",mapWebSocket.getSessionPool().size());
List listData = CoordsListData.getListData();
Thread.sleep(2000);
for (int i = 0; i < listData.size(); i++) {
if(mapWebSocket.getSessionPool().size()>0){
mapWebSocket.sendoneMessage(clientId, JSON.toJSonString(listData.get(i)));
log.info("给设备发送的信息{}",JSON.toJSonString(listData.get(i)));
Thread.sleep(600);
}
}
}
}
推送的测试数据
package cn.xiaoshuai.wsapp.contants;
import cn.hutool.core.util.RandomUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@AllArgsConstructor
public class CoordsListData {
private String addrName;
private String lat;
private String lng;
private Integer vehicleFlowrate;
public static List getListData(){
List list = new ArrayList<>();
list.add(new CoordsListData("龙蟠路", "30.259655046016114", "120.21467697651771", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("莫愁路", "30.25812", "120.197782", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("虎踞路", "30.26348489642777", "120.20715646244552", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("长乐路", "30.256701837913106", "120.22269760566824", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("乌衣巷", "30.253060723104245", "120.2196008664723", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("长干里", "30.260706", "120.201054", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("丹凤街", "30.25704913722608", "120.21339786011075", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("雨花巷", "30.257682710325838", "120.20736949202505", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("御道街", "30.251541085334537", "120.21344555780313", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("清凉古道", "30.253051", "120.198866", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("升景坊", "30.253236", "120.20659", RandomUtil.randomInt(1000)));
list.add(new CoordsListData("龙蟠路", "30.259655046016114", "120.21467697651771", RandomUtil.randomInt(2000)));
return list;
}
}
写一个页面
1.打开页面即打开websocket,并与服务端进行通信
2.为了测试效果。客户端ID 固定写死了一个
实时路况



