之前有做过车联网项目,gps设备都会有上下线检测的功能,但有的时候没有真实设备测试,如何模拟设备上下线呢?可以使用websocket实现,因为它是长连接,性能开销小且通信高效。
下面就直接上代码
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> <version>1.3.5.RELEASE</version> </dependency> </dependencies> |
DemoApplication.java
1 2 3 4 5 6 |
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } |
WebSocketServer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
package com.example.demo.websocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; @ServerEndpoint(value = "/{deviceId}") @Component public class WebSocketServer { private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class); /** * 存放每个客户端对应的MyWebSocket对象 */ private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>(); /** * 与某个客户端的连接会话,需要通过它来给客户端发送数据 */ private Session session; /** * 连接建立成功调用的方法 * */ @OnOpen public void onOpen(Session session,@PathParam(value = "deviceId") String deviceId) { this.session = session; //判断当前设备是否已有web socket连接,有则删除 deleteWebsocketExisted(deviceId); //保存当前websocket连接 webSocketMap.put(deviceId, this); // 通知客户端建立连接成功 sendMessage(deviceId + "connected success"); //设备状态变化(设备连接成功通知) statusChange(deviceId, true); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * */ @OnMessage public void onMessage(String message) { if("ping".equals(message)){ // 心跳 sendMessage(message); }else{ // 省略业务消息处理步骤 // 返回消息给客户端 sendMessage("some message"); } } /** * 连接关闭调用的方法 * */ @OnClose public void onClose() { String deviceId = getKey(webSocketMap, this); // 从set中删除 webSocketMap.remove(deviceId); //设备下线 statusChange(deviceId, false); } /** * 发生错误时调用 * */ @OnError public void onError(Throwable error) { logger.error("Error:"+error.getMessage()); } private void statusChange(String deviceId, boolean status) { if (status) { logger.info("设备{}上线", deviceId); }else{ logger.info("设备{}下线", deviceId); } // 省略操作数据库步骤 } private void deleteWebsocketExisted(String deviceId) { WebSocketServer oldConnection = webSocketMap.get(deviceId); if(null != oldConnection){ try { oldConnection.getSession().close(); } catch (IOException e) { logger.error("IOException:{}"+e.getMessage()); } } } /** * 根据map的value获取map的key * @param map * @param myWebSocket * @return */ private static String getKey(Map<String,WebSocketServer> map,WebSocketServer myWebSocket){ String key=""; for (Entry<String, WebSocketServer> entry : map.entrySet()) { if(myWebSocket.equals(entry.getValue())){ key=entry.getKey(); } } return key; } public void sendMessage(String message) { this.session.getAsyncRemote().sendText(message); } public Session getSession() { return session; } } |
WebSocketConfig.java
1 2 3 4 5 6 7 8 9 10 11 |
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(); } } |
application.properties
1 |
server.port=5656 |
启动springboot,这时就可以在客户端模拟调用了,就是这个地址
1 |
ws://localhost:5656/123456789 |
123456789是设备id
问题总结
1.WebSocketServer里是无法通过@autowired或者@resource注入bean的
2.如果是打包成war到外部tomcat运行,则不需要WebSocketConfig.java这个配置类
0