websocket的实现方式

mac2024-05-18  31

前言

利用websocket实现与网页互动,消息推送点对点消息推送,还有一种springboot的实现,下次再说

配置:

package com.zoo.websocket.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; /** * @author: 谢飞 */ @Configuration public class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }

服务端:

package com.zoo.websocket.server; import lombok.extern.slf4j.Slf4j; 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.concurrent.CopyOnWriteArraySet; /** * @author: 谢飞 */ @Slf4j @ServerEndpoint("/websocket/server/{sid}") @Component public class WebSocketServer { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; //接收sid private String sid = ""; /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam("sid") String sid) { this.session = session; //加入set中 webSocketSet.add(this); //在线数加1 addOnlineCount(); log.info("有新窗口开始监听:" + sid + ",当前在线人数为" + getOnlineCount()); this.sid = sid; try { sendMessage("连接成功"); } catch (IOException e) { log.error("websocket IO异常"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { //从set中删除 webSocketSet.remove(this); //在线数减1 subOnlineCount(); log.info("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 */ @OnMessage public void onMessage(String message, Session session) { log.info("收到来自窗口" + sid + "的信息:" + message); //群发消息 for (WebSocketServer item : webSocketSet) { try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } } /** * 发生错误 */ @OnError public void onError(Session session, Throwable error) { log.error("发生错误"); error.printStackTrace(); } /** * 实现服务器主动推送 */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } /** * 群发自定义消息 */ public static void sendInfo(String message, @PathParam("sid") String sid) throws IOException { log.info("推送消息到窗口" + sid + ",推送内容:" + message); for (WebSocketServer item : webSocketSet) { try { //这里可以设定只推送给这个sid的,为null则全部推送 if (sid == null) { item.sendMessage(message); } else if (item.sid.equals(sid)) { item.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketServer.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketServer.onlineCount--; } }

测试:

package com.zoo.websocket.controller; import com.zoo.base.bean.Resp; import com.zoo.websocket.server.WebSocketServer; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.io.IOException; /** * @author: 谢飞 */ @Controller public class TestController { @GetMapping("/") public String index(String sid, Model model) { if (StringUtils.isBlank(sid)) { model.addAttribute("websocketUrl", "ws://localhost:3000/websocket/server/null"); } else { model.addAttribute("websocketUrl", "ws://localhost:3000/websocket/server/" + sid); } return "index"; } //推送数据接口 @ResponseBody @RequestMapping("/push") public Resp pushToWeb(String sid, String message) { try { WebSocketServer.sendInfo(message, sid); } catch (IOException e) { e.printStackTrace(); return Resp.fail(sid + "#" + e.getMessage()); } return Resp.ok(sid); } } <!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <input id="websocketUrl" type="hidden" th:value="${websocketUrl}"/> </body> <script> var socket; if (typeof (WebSocket) == "undefined") { console.log("您的浏览器不支持WebSocket"); } else { console.log("您的浏览器支持WebSocket"); //实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接 socket = new WebSocket(document.getElementById("websocketUrl").value); //打开事件 socket.onopen = function () { console.log("Socket 已打开"); //socket.send("这是来自客户端的消息" + location.href + new Date()); }; //获得消息事件 socket.onmessage = function (msg) { console.log(msg.data); //发现消息进入,开始处理前端触发逻辑 }; //关闭事件 socket.onclose = function () { console.log("Socket已关闭"); }; //发生了错误事件 socket.onerror = function () { alert("Socket发生了错误"); //此时可以尝试刷新页面 } } </script> </html>

 

最新回复(0)