标签:监听 定义 通信 zed sockets 需要 apache eth throwable
最近啊,boss 跟我说,我们的系统需要有消息推送功能,他说可以使用 dwt 或者是我自己找一个框架进行推送,我因为之前的公司就是使用的 websocket,所以我选择了 websocket。
websocket 是一种新的接口协议,请求的时候需要带上前缀 ws : ws://www.demo.com 他可以保证会话的长链接,比在 http 设置 keepAlive 效果能好一些,相比轮询、长连接能效率更高一些。
废话不多说,开始上代码吧。
1. 我使用的 maven 进行代码管理,所以呢首先需要设置 jar 包依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>5.0.7.RELEASE</version> </dependency>
2. 编写 java 代码
package com.goldenstone.stuapp_web.ws; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.apache.log4j.Logger; /** * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 */ @ServerEndpoint(value = "/websocket") public class WebSocketTest { private static Logger logger = Logger.getLogger(WebSocketTest.class); // 线程安全的静态变量,表示在线连接数 private static volatile int onlineCount = 0; // 这个类不交由spring管理? // 用来存放每个客户端对应的WebSocketTest对象,适用于同时与多个客户端通信 public static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>(); // 若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 // ConcurrentHashMap 线程安全,比 hashtable 效率高一些,用空间换时间 public static ConcurrentHashMap<Session, Object> webSocketMap = new ConcurrentHashMap<Session, Object>(); // 与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户) private Session session; /** * 连接建立成功调用的方法 * * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ @OnOpen public void onOpen(Session session) { this.session = session; webSocketSet.add(this); // 加入set中 webSocketMap.put(session, this); // 加入map中 addOnlineCount(); // 在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose(Session closeSession) { webSocketSet.remove(this); // 从set中删除 webSocketMap.remove(closeSession); // 从map中删除 subOnlineCount(); // 在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message, Session mySession) throws Exception { logger.info("来自客户端的消息:" + message); // --------------群发消息(多用于聊天室场景) /* * for (WebSocketTest item : webSocketSet) { try { item.sendAllMessage(message); * } catch (IOException e) { e.printStackTrace(); continue; } } */ // 推送给单个客户端 for (Session session : webSocketMap.keySet()) { if (session.equals(mySession)) { WebSocketTest item = (WebSocketTest) webSocketMap.get(mySession); try { String msg = "嗨,这是返回的信息"; item.sendMessage(mySession, msg); } catch (IOException e) { e.printStackTrace(); } } } } /** * 发生错误时调用 * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { logger.info("发生错误"); // error.printStackTrace(); } // 给所有客户端发送信息 public void sendAllMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } // 定向发送信息 public void sendMessage(Session mySession, String message) throws IOException { synchronized (this) { try { if (mySession.isOpen()) {// 该session如果已被删除,则不执行发送请求,防止报错 // this.session.getBasicRemote().sendText(message); mySession.getBasicRemote().sendText(message); } } catch (IOException e) { e.printStackTrace(); } } } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebSocketTest.onlineCount++; } public static synchronized void subOnlineCount() { WebSocketTest.onlineCount--; } }
3. 编写前端代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- <meta http-equiv="refresh" content="1;url=http://www.taobao.com"> --> <title>Insert title here</title> <!-- url引用两种写法,都行,在这个html中css引用、js引用,使用了2钟写法 --> <link rel="stylesheet" th:href="@{/layui/css/layui.css}" id="bscss"></link> <script src="/stuapp_web/layui/layui.js" charset="utf-8"></script> <script src="/stuapp_web/jquery-3.3.1.js" charset="utf-8"></script> <script type="text/javascript"> // $(function () { // storeTempCode(); // }); </script> </head> <body> server地址 : <input id ="serveraddress" type="text" value="10.10.18.179:8080/stuapp_web"/><br/> 您的用户id : <input id ="userId" type="text" /><br/> <button onclick="initSocket()">连接</button><br/> =====================================================<br/> 消息 : <input id ="message" type="text" /><br/> <button onclick="send()">发送</button><br/> =====================================================<br/> 连接状态 : <button onclick="clearConnectStatu()">清空</button><br/> <div id="connectStatu"></div><br/> =====================================================<br/> 收到消息 :<br/> <div id="receivedMessage"></div><br/> =====================================================<br/> 心跳 :<br/> <div id="heartdiv"></div><br/> </body> <script src="<%=basePath%>/resources/jquery-1.7.2.min.js"></script> <script type="text/javascript"> var heartflag = false; var webSocket = null; // websocket全局变量 var tryTime = 0; $(function () { // initSocket(); window.onbeforeunload = function () { }; }); /** * 初始化websocket,建立连接 */ function initSocket() { var serveraddress = $("#serveraddress").val(); var userId = $("#userId").val(); if (!window.WebSocket) { // 判断浏览器是否支持 websocket $("#connectStatu").append(getNowFormatDate()+" 您的浏览器不支持ws<br/>"); return false; } webSocket = new WebSocket("ws://"+serveraddress+"/websocket"); // 收到服务端消息 webSocket.onmessage = function (msg) { if(msg.data == "&"){ }else{ $("#receivedMessage").append(getNowFormatDate()+" 收到消息 : "+msg.data+"<br/>"); } }; // 异常 webSocket.onerror = function (event) { heartflag = false; $("#connectStatu").append(getNowFormatDate()+" 异常<br/>"); }; // 建立连接 webSocket.onopen = function (event) { heartflag = true; heart(); $("#connectStatu").append(getNowFormatDate()+" 建立连接成功<br/>"); tryTime = 0; }; // 断线重连 webSocket.onclose = function () { heartflag = false; // 重试10次,每次之间间隔10秒 if (tryTime < 10) { setTimeout(function () { webSocket = null; tryTime++; initSocket(); $("#connectStatu").append( getNowFormatDate()+" 第"+tryTime+"次重连<br/>"); }, 3*1000); } else { alert("重连失败."); } }; } function send(){ var message = $("#message").val(); webSocket.send(message); } function clearConnectStatu(){ $("#connectStatu").empty(); } function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var seperator2 = ":"; var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate + " " + date.getHours() + seperator2 + date.getMinutes() + seperator2 + date.getSeconds(); return currentdate; } function heart() { if (heartflag){ webSocket.send("&"); $("#heartdiv").append(getNowFormatDate()+" 心跳 <br/>"); } setTimeout("heart()", 10*60*1000); } </script> </html>
4. 页面效果
暂时就到这里了,然后我会慢慢修改的
就是靠这口吃饭的,我会一直更下去的
标签:监听 定义 通信 zed sockets 需要 apache eth throwable
原文地址:https://www.cnblogs.com/season1992/p/9729507.html