因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端
org.springframework.boot spring-boot-starter-websocket
WebSocketConfig启用WebSocket的支持
@Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
WebSocketServer
因为WebSocket是类似客户端服务端的形式(采用ws协议),那么这里的WebSocketServer其实就相当于一个ws协议的Controller
直接@ServerEndpoint("/imserver/{userId}") 、@Component启用即可,然后在里面实现@OnOpen开启连接,@onClose关闭连接,@onMessage接收消息等方法。
新建一个ConcurrentHashMap webSocketMap 用于接收当前userId的WebSocket,方便IM之间对userId进行推送消息。单机版实现到这里就可以。
集群版(多个ws节点)还需要借助mysql或者redis等进行处理,改造对应的sendMessage方法即可。
@ServerEndpoint("/imserver/{userId}") @Component public class WebSocketService { private static ConcurrentHashMapwebSocketMap = new ConcurrentHashMap<>(); private Session session; private String userId = ""; @OnOpen public void onOpen(Session session, @PathParam("userId") String userId) { this.session = session; this.userId = userId; if (webSocketMap.containsKey(userId)) { webSocketMap.remove(userId); webSocketMap.put(userId, this); //加入set中 } else { webSocketMap.put(userId, this); //加入set中 } //服务端向客户端发送信息 sendMessage("用户" + userId + "上线了,当前在线人数为:" + webSocketMap.size() + "。"); } @OnError public void onError(Session session, Throwable error) { error.printStackTrace(); } public void sendMessage(String message) { try { this.session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } public static void sendInfo(String message, String userId, String toUserId) { //log.info("发送消息到:"+userId+",报文:"+message); if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) { webSocketMap.get(toUserId).sendMessage(message); } else { webSocketMap.get(userId).sendMessage(toUserId + "已经下线。"); } } public static void close(String userId) { if (webSocketMap.containsKey(userId)) { webSocketMap.remove(userId); } } public static Map getOnlineUser() { return webSocketMap; } }
controller 对外提供发送 关闭websocket方法
@RestController public class DemoController { @PostMapping("/push") public ResponseEntitypushToWeb(String message, String toUserId,String userId) throws IOException { WebSocketService.sendInfo(message,userId,toUserId); return ResponseEntity.ok("MSG SEND SUCCESS"); } @GetMapping("/close") public String close(String userId){ WebSocketService.close(userId); return "ok"; } @GetMapping("/getOnlineUser") public Map getOnlineUser(){ return WebSocketService.getOnlineUser(); } }
html 前端页面
websocket通讯 【内容】:
【当前用户】:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)