java websocket时时通信
基本案例是网上爬的,改了很多,单纯发文字聊天功能完整, 1对1单聊, 离线用户能接受到另一方的留言,增加了一张数据库表,如果不用表保存离线数据,也可以选择单例模式缓存来保存。测试了下还可以哦!直接贴代码不明白的可以问我。
java服务端:
package websockets; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.time.DateFormatUtils; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.springframework.http.server.ServletServerHttpRequest; import Helper.AAAAYulebaoShareSingleton; import Helper.MySqlHepler2; import Helper.EncryptSafa; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; //auth:liaohang @ServerEndpoint("/javaWebSocket") public class javaWebSocket { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static int onlineCount = 0; //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 // private static CopyOnWriteArraySet<javaWebSocket> webSocketSets = new CopyOnWriteArraySet<javaWebSocket>(); private static JSONObject webSocketSets = new JSONObject(); //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; private String[] parameterArr; private String shareStr; private String userKey; private String shopKey; private String type; //这里来个请求的httpRequest类 /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ private javaWebSocket chatmemeber; //数据库操作参数 private MySqlHepler2 helper=new MySqlHepler2(); private JSONArray returnJsonArray; private String[] mysqlParameter=null; private JSONObject shareObject; private String datatime; private int shareInt=0; @OnOpen public void onOpen(Session session){ this.session = session; shareStr= session.getRequestURI().toString(); shareStr=shareStr.replace("/yulebaoServlet/javaWebSocket?", ""); shareStr=shareStr.replace("user=", ""); shareStr=shareStr.replace("shop=", ""); shareStr=shareStr.replace("type=", ""); parameterArr=shareStr.split("&"); type=parameterArr[2]; if(type.equals("user")) { userKey=parameterArr[0]; shopKey=parameterArr[1]; webSocketSets.put(userKey, this); //查询一次数据库,看是有人在我离线时给我发了消息 mysqlParameter=new String[]{userKey}; returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where sessionKey=?", mysqlParameter); try { shareInt=returnJsonArray.length(); } catch (Exception e) { shareInt=0; } if(returnJsonArray.length()>0) { shareObject=returnJsonArray.getJSONObject(0); shareStr= shareObject.getString("chatContentArray"); try { this.sendMessage(shareStr); } catch (IOException e) { e.printStackTrace(); } mysqlParameter=new String[]{userKey}; helper.executeUpdate("delete from AAAAAAAAAChatSheet where sessionKey=?", mysqlParameter); } } else { userKey=parameterArr[0]; shopKey=parameterArr[1]; webSocketSets.put(shopKey, this); //查询一次数据库,看是有人在我离线时给我发了消息 mysqlParameter=new String[]{shopKey}; returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where sessionKey=?", mysqlParameter); try { shareInt=returnJsonArray.length(); } catch (Exception e) { shareInt=0; } if(returnJsonArray.length()>0) { shareObject=returnJsonArray.getJSONObject(0); shareStr= shareObject.getString("chatContentArray"); try { this.sendMessage(shareStr); } catch (IOException e) { e.printStackTrace(); } //删除key mysqlParameter=new String[]{shopKey}; helper.executeUpdate("delete from AAAAAAAAAChatSheet where sessionKey=?", mysqlParameter); } } //加入set中 addOnlineCount(); //在线数加1 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); } /** * 连接关闭调用的方法 */ @OnClose public void onClose(){ if(type.equals("user")) { if(!webSocketSets.isNull(userKey)) { webSocketSets.remove(userKey); } } else { if(!webSocketSets.isNull(shopKey)) { webSocketSets.remove(shopKey); } } //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * @param message 客户端发送过来的消息 * @param session 可选的参数 */ @OnMessage public void onMessage(String message, Session session) { System.out.println("来自客户端的消息:" + message); //群发消息 if(type.equals("user")) { if(!webSocketSets.isNull(shopKey)) { chatmemeber=(javaWebSocket)webSocketSets.get(shopKey); try { chatmemeber.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } else { insertDataBase(shopKey,message); } } else { if(!webSocketSets.isNull(userKey)) { chatmemeber=(javaWebSocket)webSocketSets.get(userKey); try { chatmemeber.sendMessage(message); } catch (IOException e) { e.printStackTrace(); } } else { //接消息以方不在,插入数据库保存 insertDataBase(userKey,message); } } //1对多发消息 /* for(javaWebSocket item: webSocketSets){ try { item.sendMessage(message); } catch (IOException e) { e.printStackTrace(); continue; } }*/ } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ System.out.println("发生错误"); error.printStackTrace(); } /** * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 * @param message * @throws IOException */ public void sendMessage(String message) throws IOException{ this.session.getBasicRemote().sendText(message); //this.session.getAsyncRemote().sendText(message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { javaWebSocket.onlineCount++; } public static synchronized void subOnlineCount() { javaWebSocket.onlineCount--; } //当一方用户下线之后,如果再发消息,需要将接收消息保存到数据库 public void insertDataBase(String shareKey,String message) { shareObject=new JSONObject(); datatime=DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm"); shareObject.put("datatime", datatime); shareObject.put("message", message); mysqlParameter=new String[]{shareKey}; returnJsonArray=helper.executeQueryT("select * from AAAAAAAAAChatSheet where sessionKey=?", mysqlParameter); try { shareInt=returnJsonArray.length(); } catch(Exception e) { shareInt=0; returnJsonArray=new JSONArray(); } if(shareInt==0) //插入数据 { returnJsonArray.put(shareObject); mysqlParameter=new String[]{shareKey,datatime,returnJsonArray.toString()}; helper.executeUpdate("insert into AAAAAAAAAChatSheet(sessionKey,sessionCreateTimes,chatContentArray)values(?,?,?)", mysqlParameter); } else//更新连端的数据 { returnJsonArray.put(shareObject); mysqlParameter=new String[]{returnJsonArray.toString(),shareKey}; helper.executeUpdate("update AAAAAAAAAChatSheet set chatContentArray=? where sessionKey=?", mysqlParameter); } } }
前端页面User方:
<%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>Java后端WebSocket的Tomcat实现</title> </head> <body> Welcome<br/><input id="text" type="text"/> <button onclick="send()">发送消息</button> <hr/> <button onclick="closeWebSocket()">关闭WebSocket连接</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { //第一个创建链接的用户需要两个key,创建一个webosckt链接。为了保证JSONObject单个创建的websocket key唯一 所以参数就用双方的唯一账户或id正反组合+类型' //为什么要传两个key?比如这个是user请求的链接,他创建websocket时需要查询一下对方有没有离线留言,如果有离线留言得访问一次数据库读出来返回,所以shop这个key也必须带上 var user="liaohang"+"xiaoming"+"user"; var shop="xiaoming"+"liaohang"+"shop"; websocket = new WebSocket("ws://localhost:8080/yulebaoServlet/javaWebSocket?user="+user+"&shop="+shop+"&type=user"); } else { alert('当前浏览器 Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket连接发生错误"); }; //连接成功建立的回调方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket连接成功"); } //接收到消息的回调方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭WebSocket连接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
前端页面Shop方:
<%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE html> <html> <head> <title>Java后端WebSocket的Tomcat实现</title> </head> <body> Welcome<br/><input id="text" type="text"/> <button onclick="send()">发送消息</button> <hr/> <button onclick="closeWebSocket()">关闭WebSocket连接</button> <hr/> <div id="message"></div> </body> <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket' in window) { //Id account+对方的account +type 接单者发起请求 var user="liaohang"+"xiaoming"+"user"; var shop="xiaoming"+"liaohang"+"shop"; websocket = new WebSocket("ws://localhost:8080/yulebaoServlet/javaWebSocket?user="+user+"&shop="+shop+"&type=shop"); } else { alert('当前浏览器 Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function () { setMessageInnerHTML("WebSocket连接发生错误"); }; //连接成功建立的回调方法 websocket.onopen = function () { setMessageInnerHTML("WebSocket连接成功"); } //接收到消息的回调方法 websocket.onmessage = function (event) { setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function () { setMessageInnerHTML("WebSocket连接关闭"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function () { closeWebSocket(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭WebSocket连接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { var message = document.getElementById('text').value; websocket.send(message); } </script> </html>
前端页面User方和 Shop方 不同的就是传参数的类型
https://www.bai6du.com/yulebaoServlet/talkTest.jsp