当时要写这个需求的时候,很头痛,手机端页面的客服功能,相当于QQ这样一个一对一聊天室功能了,瞬间蒙蔽的我也不知道用什么去写这个东西,一开始用ajax,定时器去写,写着写着发现这尼玛不在同一个页面怎么做数据传输,而且很难做到点对点信息聊天。郁闷了几个小时后决定用websocket试着去学习然后去写这个聊天功能。写到半截才知道网上客服功能都是买的叫IM即时通讯,网易云是1800一个月,当时就吐了一碗血,调调接口就行了,还写了三天左右的websocket,BOSS赶紧感激我每年给他活活省了21600.
废话少说上代码。
首先我们把PC端的页面代码跟手机端的页面代码放到一个jsp文件中去,根据屏幕的分辨率分别叫他们显示手机端页面或者PC端页面。
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 4 <%@ include file="/login/path.jsp"%> 5 6 <html> 7 8 <head> 9 <meta charset="utf-8"> 10 <title>阿斯蒂芬</title> 11 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 12 <meta name="author" content="jQuery插件库(www.jq22.com)"> 13 <meta name="weburl" content="http://www.jq22.com/"> 14 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> 15 <link rel="stylesheet" href="<%=basePath%>css/reset.css"> 16 <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> 17 <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 18 <link rel="stylesheet" href="<%=basePath%>css/cS.css" media="only screen and (max-width:1024px)"> 19 <link rel="stylesheet" type="text/css" href="<%=basePath%>css/qq.css" media="only screen and (min-width:1025px)"> 20 </head> 21 22 <body> 23 <input type="hidden" value="or-bevkBoF0HWRS3d4M2MAXdb9yE" id="openid" /> 24 <div class="wrap"> 25 <div class="menu"> 26 <p>每天9:30-18:00在线</p> 27 <span>退出客服</span> 28 </div> 29 <div class="talk"> 30 <div class="time">${dateTime }</div> 31 <div class="serviceCustom" id="APPContent"> 32 <c:forEach items="${contentList}" var="contentList" varStatus="vs"> 33 <div> 34 <p class="servicejiao"></p> 35 <p class="serviceword">${contentList.customerService_content }</p> 36 </div> 37 </c:forEach> 38 </div> 39 <!-- <div class="custom" id="faceImg"> 40 41 </div> --> 42 </div> 43 <div class="downfoot"> 44 <div class="up"> 45 <span class="glyphicon glyphicon-apple emotion"></span> 46 <span id="chooseImage" class="glyphicon glyphicon-picture"></span> 47 </div> 48 <div class="down"> 49 50 <input class="input" id="saytext" name="saytext" placeholder="输入新消息"> 51 <button class="send sub_btn" type="button">发送</button> 52 </div> 53 </div> 54 </div> 55 <!-- ================================================================= --> 56 57 <div class="qqBox"> 58 <div class="BoxHead"> 59 <div class="headImg"> 60 <img src="<%=basePath%>arclist/logo.png"/> 61 </div> 62 <div class="internetName">阿斯顿发射点</div> 63 </div> 64 <div class="context"> 65 <div class="conLeft"> 66 <ul id="liContent"> 67 <%-- <li class="bg"> 68 <div class="liLeft"><img src="<%=basePath%>arclist/tx.png"/></div> 69 <div class="liRight"> 70 <span class="intername">赵鹏1 </span> 71 <span class="badge">5</span> 72 <span class="infor">[流泪]</span> 73 <!-- <input type="hidden" value="" id="valueNum"/> --> 74 </div> 75 </li> --%> 76 </ul> 77 </div> 78 <div class="conRight"> 79 <div class="Righthead" id="name"> 80 <!-- <div class="headName">赵鹏</div> --> 81 </div> 82 <div class="RightCont"> 83 <ul class="newsList" id="PCContent"> 84 85 </ul> 86 </div> 87 <div class="RightFoot"> 88 <div class="emjon"> 89 <ul> 90 <li><img src="<%=basePath%>arclist/1.gif"/></li> 91 <li><img src="<%=basePath%>arclist/2.gif"/></li> 92 <li><img src="<%=basePath%>arclist/3.gif"/></li> 93 <li><img src="<%=basePath%>arclist/4.gif"/></li> 94 <li><img src="<%=basePath%>arclist/5.gif"/></li> 95 <li><img src="<%=basePath%>arclist/6.gif"/></li> 96 <li><img src="<%=basePath%>arclist/7.gif"/></li> 97 <li><img src="<%=basePath%>arclist/8.gif"/></li> 98 <li><img src="<%=basePath%>arclist/9.gif"/></li> 99 <li><img src="<%=basePath%>arclist/10.gif"/></li> 100 <li><img src="<%=basePath%>arclist/11.gif"/></li> 101 <li><img src="<%=basePath%>arclist/12.gif"/></li> 102 <li><img src="<%=basePath%>arclist/13.gif"/></li> 103 <li><img src="<%=basePath%>arclist/14.gif"/></li> 104 <li><img src="<%=basePath%>arclist/15.gif"/></li> 105 <li><img src="<%=basePath%>arclist/16.gif"/></li> 106 <li><img src="<%=basePath%>arclist/17.gif"/></li> 107 <li><img src="<%=basePath%>arclist/18.gif"/></li> 108 <li><img src="<%=basePath%>arclist/19.gif"/></li> 109 <li><img src="<%=basePath%>arclist/20.gif"/></li> 110 <li><img src="<%=basePath%>arclist/21.gif"/></li> 111 <li><img src="<%=basePath%>arclist/22.gif"/></li> 112 <li><img src="<%=basePath%>arclist/23.gif"/></li> 113 <li><img src="<%=basePath%>arclist/24.gif"/></li> 114 <li><img src="<%=basePath%>arclist/25.gif"/></li> 115 <li><img src="<%=basePath%>arclist/26.gif"/></li> 116 <li><img src="<%=basePath%>arclist/27.gif"/></li> 117 <li><img src="<%=basePath%>arclist/28.gif"/></li> 118 <li><img src="<%=basePath%>arclist/29.gif"/></li> 119 <li><img src="<%=basePath%>arclist/30.gif"/></li> 120 <li><img src="<%=basePath%>arclist/31.gif"/></li> 121 <li><img src="<%=basePath%>arclist/32.gif"/></li> 122 <li><img src="<%=basePath%>arclist/33.gif"/></li> 123 <li><img src="<%=basePath%>arclist/34.gif"/></li> 124 <li><img src="<%=basePath%>arclist/35.gif"/></li> 125 <li><img src="<%=basePath%>arclist/36.gif"/></li> 126 <li><img src="<%=basePath%>arclist/37.gif"/></li> 127 <li><img src="<%=basePath%>arclist/38.gif"/></li> 128 <li><img src="<%=basePath%>arclist/39.gif"/></li> 129 <li><img src="<%=basePath%>arclist/40.gif"/></li> 130 <li><img src="<%=basePath%>arclist/41.gif"/></li> 131 <li><img src="<%=basePath%>arclist/42.gif"/></li> 132 <li><img src="<%=basePath%>arclist/43.gif"/></li> 133 <li><img src="<%=basePath%>arclist/44.gif"/></li> 134 <li><img src="<%=basePath%>arclist/45.gif"/></li> 135 <li><img src="<%=basePath%>arclist/46.gif"/></li> 136 <li><img src="<%=basePath%>arclist/47.gif"/></li> 137 <li><img src="<%=basePath%>arclist/48.gif"/></li> 138 <li><img src="<%=basePath%>arclist/49.gif"/></li> 139 <li><img src="<%=basePath%>arclist/50.gif"/></li> 140 <li><img src="<%=basePath%>arclist/51.gif"/></li> 141 <li><img src="<%=basePath%>arclist/52.gif"/></li> 142 <li><img src="<%=basePath%>arclist/53.gif"/></li> 143 <li><img src="<%=basePath%>arclist/54.gif"/></li> 144 <li><img src="<%=basePath%>arclist/55.gif"/></li> 145 <li><img src="<%=basePath%>arclist/56.gif"/></li> 146 <li><img src="<%=basePath%>arclist/57.gif"/></li> 147 <li><img src="<%=basePath%>arclist/58.gif"/></li> 148 <li><img src="<%=basePath%>arclist/59.gif"/></li> 149 <li><img src="<%=basePath%>arclist/60.gif"/></li> 150 <li><img src="<%=basePath%>arclist/61.gif"/></li> 151 <li><img src="<%=basePath%>arclist/62.gif"/></li> 152 <li><img src="<%=basePath%>arclist/63.gif"/></li> 153 <li><img src="<%=basePath%>arclist/64.gif"/></li> 154 <li><img src="<%=basePath%>arclist/65.gif"/></li> 155 <li><img src="<%=basePath%>arclist/66.gif"/></li> 156 <li><img src="<%=basePath%>arclist/67.gif"/></li> 157 <li><img src="<%=basePath%>arclist/68.gif"/></li> 158 <li><img src="<%=basePath%>arclist/69.gif"/></li> 159 <li><img src="<%=basePath%>arclist/70.gif"/></li> 160 <li><img src="<%=basePath%>arclist/71.gif"/></li> 161 <li><img src="<%=basePath%>arclist/72.gif"/></li> 162 <li><img src="<%=basePath%>arclist/73.gif"/></li> 163 <li><img src="<%=basePath%>arclist/74.gif"/></li> 164 <li><img src="<%=basePath%>arclist/75.gif"/></li> 165 </ul> 166 </div> 167 <div class="footTop"> 168 <ul> 169 <li class="ExP"><img src="<%=basePath%>arclist/download-14.jpg"/></li> 170 <li><img src="<%=basePath%>arclist/download-18.jpg"/></li> 171 </ul> 172 </div> 173 <div class="inputBox"> 174 <textarea id="dope" style="width: 99%;height: 75px; border: none;outline: none;" name="" rows="" cols=""></textarea> 175 <button class="sendBtn">发送(s)</button> 176 </div> 177 </div> 178 </div> 179 </div> 180 </div> 181 </body> 182 <script src="<%=basePath%>js/touch-0.2.14.min.js"></script> 183 <script src="<%=basePath%>js/size.js"></script> 184 <script src="<%=basePath%>js/jquery.min.js"></script> 185 <script type="text/javascript" src="<%=basePath%>js/jquery.qqFace.js"></script> 186 <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"> </script> 187 188 <script> 189 (function(){ 190 if (document.body.clientWidth<=1024){ 191 $(".wrap").css("visibility","none"); 192 $(".qqBox").css("visibility","hidden"); 193 document.writeln("<script type=\"text/javascript\" src=\"../js/cS.js\"><\/script>"); 194 }else { 195 $(".wrap").css("visibility","hidden"); 196 $(".qqBox").css("visibility","none"); 197 document.writeln("<script type=\"text/javascript\" src=\"../js/qq.js\"><\/script>"); 198 } 199 })(); 211 </script> 212 213 </html>
当我初始化打开或者刷新这个页面的时候就会自动链接跟断开websocket。如果我以手机屏幕展现出来的时候他会只加载cs.js以PC端屏幕展现只会加载qq.js,下面分别是两个js文件内容。
cs.js
1 var ipt=$(".wrap .downfoot .down input"); 2 var send=$(".wrap .downfoot .down .send"); 3 var serviceCustom=$(".wrap .talk .serviceCustom"); 4 var talk=$(".wrap .talk"); 5 var menu=$(".wrap .menu"); 6 var gif=$(".wrap .gif"); 7 var gifSpan=$(".wrap .gif div span"); 8 var sumTop=0; 9 10 11 12 $(function(){ 13 $(\'.emotion\').qqFace({ 14 15 id : \'facebox\', 16 17 assign:\'saytext\', 18 19 path:\'../arclist/\' //表情存放的路径 20 21 }); 22 23 ipt[0].oninput = function() { 24 if (ipt[0].value) { 25 send.css({ 26 backgroundColor:"#b0070e" 27 }) 28 }else { 29 send.css({ 30 backgroundColor:"lightgray" 31 }) 32 } 33 } 34 var websocket = null; 35 //判断当前浏览器是否支持WebSocket 36 if (\'WebSocket\' in window) { 37 websocket = new WebSocket("ws://localhost:8080/jhmyManage/websocket/1"); 38 } 39 else { 40 alert(\'当前浏览器 Not support websocket\') 41 } 42 43 //连接发生错误的回调方法 44 websocket.onerror = function () { 45 /*setMessageInnerHTML("WebSocket连接发生错误");*/ 46 }; 47 48 //连接成功建立的回调方法 49 websocket.onopen = function () { 50 /*setMessageInnerHTML("WebSocket连接成功");*/ 51 } 52 53 //接收到消息的回调方法 54 websocket.onmessage = function (event) { 55 setMessageInnerHTML(event.data); 56 } 57 58 //连接关闭的回调方法 59 websocket.onclose = function () { 60 /*setMessageInnerHTML("WebSocket连接关闭");*/ 61 } 62 63 //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 64 window.onbeforeunload = function () { 65 closeWebSocket(); 66 } 67 68 //将消息显示在网页上 69 function setMessageInnerHTML(innerHTML) { 74 if(innerHTML.indexOf("jhmyManage")>-1){ 75 $("<div><p class=serviceJiao></p><p class=serviceWord><img src="+innerHTML+" border=0 /></p></div>").appendTo("#APPContent"); 76 }else{ 77 $("<div><p class=serviceJiao></p><p class=serviceWord>"+innerHTML+"</p></div>").appendTo("#APPContent"); 78 } 79 } 80 81 //关闭WebSocket连接 82 function closeWebSocket() { 83 websocket.close(); 84 } 85 //发送消息 86 send.click(function(){ 87 if (ipt[0].value){ 88 var topOne=talk.height(); 89 var str = $("#saytext").val(); 90 var div=document.createElement("div"); 91 // $(div).html(replace_em(str)); 92 div.innerHTML=\'<p class="customJiao"></p><p class="customWord">\'+replace_em(str)+\'</p>\'; 93 serviceCustom[0].appendChild(div); 94 ipt[0].value=""; 95 var topTwo=talk.height(); 96 sumTop+=topOne-topTwo; 97 talk.animate({ 98 top:sumTop+topTwo-topOne 99 },100); 100 send.css({ 101 backgroundColor:"lightgray" 102 }); 103 var openid = document.getElementById("openid").value; 104 websocket.send(str+","+"kehu"+","+openid); 105 } 106 }); 107 108 143 144 }); 145 146 //查看结果 147 function replace_em(str){ 148 str = str.replace(/\</g,\'<\'); 149 str = str.replace(/\>/g,\'>\'); 150 str = str.replace(/\n/g,\'<br/>\'); 151 str = str.replace(/\[em_([0-9]*)\]/g,\'<img src="../arclist/$1.gif" border="0" />\'); 152 153 return str; 154 } 155 156 // 上下滑动屏幕 157 touch.config.drag=true; 158 console.log(talk[0].style.top); 159 //定义初始位置 160 var disY=0; 161 //定义偏移量 162 var y=0; 163 touch.on(document,\'touchstart touchmove\',function(event){ 164 event.preventDefault(); 165 }); 166 touch.on(talk,\'drag\',function(event){ 167 y=disY+event.y; 168 if (y>menu.height()||$(".wrap").innerHeight()>talk.height()){ 169 y=menu.height(); 170 }else if (y<$(".wrap").innerHeight()-talk.height()){ 171 y=$(".wrap").innerHeight()-talk.height(); 172 } talk[0].style.top=y+\'px\'; 173 }); 174 touch.on(talk,\'dragend\',function(){ 175 disY=y; 176 });
qq.js文件
1 var PCindex=0;//默认左侧打开的是第一个窗口 2 var websocket = null; 3 //判断当前浏览器是否支持WebSocket 4 if (\'WebSocket\' in window) { 5 websocket = new WebSocket("ws://localhost:8080/jhmyManage/websocket/2"); 6 } 7 else { 8 alerrt(\'当前浏览器 Not support websocket\') 9 } 10 11 //连接发生错误的回调方法 12 websocket.onerror = function () { 13 /*setMessageInnerHTML("WebSocket连接发生错误");*/ 14 }; 15 16 //连接成功建立的回调方法 17 websocket.onopen = function () { 18 /*setMessageInnerHTML("WebSocket连接成功");*/ 19 } 20 21 //接收到消息的回调方法 22 websocket.onmessage = function (event) { 23 setMessageInnerHTML(event.data); 24 } 25 26 //连接关闭的回调方法 27 websocket.onclose = function () { 28 /*setMessageInnerHTML("WebSocket连接关闭");*/ 29 } 30 31 //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 32 window.onbeforeunload = function () { 33 closeWebSocket(); 34 } 35 var ipt=""; 36 //将消息显示在网页上 37 function setMessageInnerHTML(innerHTML) { 38 var re = /^[0-9]+.?[0-9]*$/; 39 var numif=""; 40 var stringNum = innerHTML.split(","); 41 var intername=$(".qqBox .context .conLeft ul li .liRight .intername"); 42 var ppppp=null; 43 if(intername.length==0){ 44 45 if (re.test(stringNum[0])) { 46 $("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' /><img class=Expr src=../arclist/"+stringNum[0]+".gif /></div></li></div>").appendTo("#PCContent"); 47 $("<li class=bg><div class=liLeft><img src=../arclist/tx.png /></div><div class=liRight><span class=intername>"+stringNum[2]+"</span><span class=badge>0</span><span class=infor >[图片]</span><input type=hidden value="+stringNum[1]+" /></div></li>").appendTo("#liContent"); 48 }else{ 49 $("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' /><span>"+stringNum[0]+"</span></div></li></div>").appendTo("#PCContent"); 50 $("<li class=bg><div class=liLeft><img src=../arclist/tx.png /></div><div class=liRight><span class=intername>"+stringNum[2]+"</span><span class=badge>0</span><span class=infor >"+stringNum[0]+"</span><input type=hidden value="+stringNum[1]+" /></div></li>").appendTo("#liContent"); 51 } 52 $("<div class=headName>"+stringNum[2]+"</div>").appendTo("#name"); 53 $("#PCContent>div")[0].showNum=1; 54 $("#liContent li")[0].children[1].children[1].innerHTML=$("#PCContent>div")[0].showNum; 55 showNum(); 56 $("#PCContent>div").css("display","none"); 57 }else{ 58 for (let i=0;i<intername.length;i++){ 59 if(intername[i].innerHTML==stringNum[2]){ 60 if (re.test(stringNum[0])) { 61 $("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' /><img class=Expr src=../arclist/"+stringNum[0]+".gif /></div></li></div>").appendTo($($("#PCContent>div")[i])); 62 }else{ 63 $("<li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' /><span>"+stringNum[0]+"</span></div></li>").appendTo($($("#PCContent>div")[i])); 64 $("#liContent li")[i].children[1].children[2].innerHTML=$("#PCContent>div")[i].lastChild.children[1].children[1].innerHTML; 65 } 66 $("#PCContent>div")[i].showNum+=1; 67 $("#liContent li")[i].children[1].children[1].innerHTML=$("#PCContent>div")[i].showNum; 68 69 showNum(); 70 //document.getElementById("contentUpdate").innerHTML=stringNum[0]; 71 numif=1; 72 } 73 } 74 if(numif!=1){ 75 /*$("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' />"+stringNum[0]+"</div></li></div>").appendTo("#PCContent"); 76 $("<li><div class=liLeft><img src=../arclist/tx.png /></div><div class=liRight><span class=intername>"+stringNum[2]+"</span><span class=badge>0</span><span class=infor id=contentUpdate>"+stringNum[0]+"</span><input type=hidden value="+stringNum[1]+" /></div></li>").appendTo("#liContent");*/ 77 if (!re.test(stringNum[1])) { 78 $("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' /><img class=Expr src=../arclist/"+stringNum[0]+".gif /></div></li></div>").appendTo("#PCContent"); 79 $("<li class=bg><div class=liLeft><img src=../arclist/tx.png /></div><div class=liRight><span class=intername>"+stringNum[2]+"</span><span class=badge>0</span><span class=infor >[图片]</span><input type=hidden value="+stringNum[1]+" /></div></li>").appendTo("#liContent"); 80 }else{ 81 $("<div><li><div class=answerHead><img src=\'../arclist/tx.png\' /></div><div class=answers><img class=jiao src=\'../arclist/jiao.jpg\' />"+stringNum[0]+"</div></li></div>").appendTo("#PCContent"); 82 $("<li class=bg><div class=liLeft><img src=../arclist/tx.png /></div><div class=liRight><span class=intername>"+stringNum[2]+"</span><span class=badge>0</span><span class=infor >"+stringNum[0]+"</span><input type=hidden value="+stringNum[1]+" /></div></li>").appendTo("#liContent"); 83 } 84 $("#PCContent>div")[$("#PCContent>div").length-1].showNum=1; 85 $("#liContent li")[$("#PCContent>div").length-1].children[1].children[1].innerHTML=$("#PCContent>div")[$("#PCContent>div").length-1].showNum; 86 showNum(); 87 $("#PCContent>div").css("display","none"); 88 } 89 } 90 91 /*document.getElementById(\'PCContent\').innerHTML += innerHTML + \'<br/>\';*/ 92 93 $(\'.conLeft li\').on(\'click\',function(){ 94 $(this).addClass(\'bg\').siblings().removeClass(\'bg\'); 95 var intername=$(this).children(\'.liRight\').children(\'.intername\').text(); 96 $(\'.headName\').text(intername); 97 ipt=$(this).children(\'.liRight\').children(\'input\').val(); 98 //$(\'.newsList\').html(\'\'); 99 PCindex=$(this).index(); 100 $($("#PCContent>div")[PCindex])[0].showNum=0; 101 console.log($($("#PCContent>div")[PCindex])[0].showNum); 102 $($("#PCContent>div")[PCindex]).css("display","block").siblings().css("display","none"); 103 showNum(); 104 $("#liContent li")[PCindex].children[1].children[1].style.display="none"; 105 }); 106 } 107 function showNum(){ 108 for (let i=0;i<$("#liContent li").length;i++){ 109 if ($($("#PCContent>div")[i])[0].showNum==0){ 110 console.log($($("#PCContent>div")[i])[0].showNum); 111 $("#liContent li")[i].children[1].children[1].style.display="none"; 112 }else { 113 console.log($($("#PCContent>div")[i])[0].showNum); 114 $("#liContent li")[i].children[1].children[1].style.display="block"; 115 } 116 } 117 } 118 119 //关闭WebSocket连接 120 function closeWebSocket() { 121 websocket.close(); 122 } 123 124 /* $(\'.conLeft li\').on(\'click\',function(){ 125 $(this).addClass(\'bg\').siblings().removeClass(\'bg\'); 126 var intername=$(this).children(\'.liRight\').children(\'.intername\').text(); 127 $(\'.headName\').text(intername); 128 //$(\'.newsList\').html(\'\'); 129 });*/ 130 131 132 $(\'.sendBtn\').on(\'click\',function(){ 133 var news=$(\'#dope\').val(); 134 if(!news){ 135 alert(\'不能为空\'); 136 }else{ 137 $(\'#dope\').val(\'\'); 138 var str=\'\'; 139 str+=\'<li>\'+ 140 \'<div class="nesHead"><img src="../arclist/logo.png"/></div>\'+ 141 \'<div class="news"><img class="jiao" src="../arclist/jiao.jpg"><span>\'+news+\'</span></div>\'+ 142 \'</li>\'; 143 $($(\'.newsList>div\')[PCindex]).append(str); 144 //setTimeout(answers,1000); 145 $(\'.conLeft\').find(\'li.bg\').children(\'.liRight\').children(\'.infor\').text(news); 146 $(\'.RightCont\').scrollTop($(\'.RightCont\')[0].scrollHeight ); 147 longLong(); 148 websocket.send(news+","+ipt); 149 } 150 }); 151 var isSend=false; 152 $(document).keydown(function(event){ 153 if (event.keyCode==13&&isSend){ 154 var news=$(\'#dope\').val(); 155 console.log(news); 156 if(!news){ 157 alert(\'不能为空\'); 158 }else{ 159 $(\'#dope\').val(\'\'); 160 var str=\'\'; 161 str+=\'<li>\'+ 162 \'<div class="nesHead"><img src="../arclist/logo.png"/></div>\'+ 163 \'<div class="news"><img class="jiao" src="../arclist/jiao.jpg"><span>\'+news+\'</span></div>\'+ 164 \'</li>\'; 165 $($(\'.newsList>div\')[PCindex]).append(str); 166 $(\'.conLeft\').find(\'li.bg\').children(\'.liRight\').children(\'.infor\').text(news); 167 $(\'.RightCont\').scrollTop($(\'.RightCont\')[0].scrollHeight ); 168 longLong(); 169 websocket.send(news+","+ipt); 170 } 171 isSend=false; 172 } 173 }); 174 $(document).keyup(function(event){ 175 if (event.keyCode==13&&!isSend){ 176 isSend=true; 177 } 178 }); 179 /*function answers(){ 180 var arr=["你好"]; 181 var aa=Math.floor((Math.random()*arr.length)); 182 var answer=\'\'; 183 answer+=\'<li>\'+ 184 \'<div class="answerHead"><img src="../arclist/tx.png"/></div>\'+ 185 \'<div class="answers"><img class="jiao" src="../arclist/jiao.jpg">\'+arr[aa]+\'</div>\'+ 186 \'</li>\'; 187 $(\'.newsList\').append(answer); 188 $(\'.RightCont\').scrollTop($(\'.RightCont\')[0].scrollHeight ); 189 }*/ 190 $(\'.ExP\').on(\'mouseenter\',function(){ 191 $(\'.emjon\').show(); 192 }) 193 $(\'.emjon\').on(\'mouseleave\',function(){ 194 $(\'.emjon\').hide(); 195 }) 196 $(\'.emjon li\').on(\'click\',function(){ 197 var imgSrc=$(this).children(\'img\').attr(\'src\'); 198 var str=""; 199 str+=\'<li>\'+ 200 \'<div class="nesHead"><img src="../arclist/logo.png"/></div>\'+ 201 \'<div class="news"><img class="jiao" src="../arclist/jiao.jpg"><img class="Expr" src="\'+imgSrc+\'"></div>\'+ 202 \'</li>\'; 203 /*$(\'.newsList\').append(str);*/ 204 $($(\'.newsList>div\')[PCindex]).append(str); 205 $(\'.emjon\').hide(); 206 $(\'.RightCont\').scrollTop($(\'.RightCont\')[0].scrollHeight ); 207 longLong(); 208 websocket.send(imgSrc+","+ipt); 209 }); 210 function longLong(){ 211 var news=document.querySelectorAll(".news"); 212 for (let i=0;i<news.length;i++){ 213 if (news[i].offsetWidth>=490){ 214 news[i].parentNode.style.height=news[i].offsetHeight+"px"; 215 } 216 } 217 }
每当你刷新页面的时候他会自动加载走后台你所定义的接口,不需要配置web.xml文件
当我发送一条信息后会自动走后台然后创建一个只属于本窗口的相应id,没打开一个手机端窗口都有一个相应的唯一值,发送信息时统一去找PC端那个id,PC端发送消息时在拿着当前用户的id去找就行了。
1 2 import java.io.IOException; 3 import java.util.HashMap; 4 import java.util.List; 5 import java.util.Map; 6 import java.util.concurrent.CopyOnWriteArraySet; 7 import java.util.concurrent.atomic.AtomicInteger; 8 import java.util.regex.Matcher; 9 import java.util.regex.Pattern; 10 11 import javax.websocket.*; 12 import javax.websocket.server.PathParam; 13 import javax.websocket.server.ServerEndpoint; 14 15 import com.bjth.bjthManage.web.customer.entity.customer; 16 import com.bjth.bjthManage.web.customer.util.customerActionUtil; 17 18 /** 19 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, 20 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端 21 */ 22 @ServerEndpoint("/websocket/{relationId}") 23 public class WebSocketTest { 24 //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 25 private static int onlineCount = 0; 26 private customerActionUtil customerUtil = new customerActionUtil(); 27 28 //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识 29 //private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>(); 30 private static final Map<String,Object> webSocketSet = new HashMap<String,Object>(); 31 private static final AtomicInteger connectionIds = new AtomicInteger(0); 32 //与某个客户端的连接会话,需要通过它来给客户端发送数据 33 private Session session; 34 private final String nickname; 35 private static final String GUEST_PREFIX = "Guest"; 36 public WebSocketTest() { 37 nickname = GUEST_PREFIX + connectionIds.getAndIncrement(); 38 System.out.println(nickname+"==当前id值是"); 39 } 40 /** 41 * 连接建立成功调用的方法 42 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 43 */ 44 @OnOpen 45 public void onOpen(@PathParam("relationId") int relationId,Session session){ 46 this.session = session; 47 //webSocketSet.add(this); //加入set中 48 webSocketSet.put(nickname, this); 49 if(relationId==2){ 50 webSocketSet.put("typeKefu", nickname); 51 } 52 53 addOnlineCount(); //在线数加1 54 System.out.println("有新连接加入!当前在线人数为" + getOnlineCount()); 55 } 56 57 /** 58 * 连接关闭调用的方法 59 */ 60 @OnClose 61 public void onClose(){ 62 webSocketSet.remove(this); //从set中删除 63 subOnlineCount(); //在线数减1 64 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); 65 } 66 67 /** 68 * 收到客户端消息后调用的方法 69 * @param message 客户端发送过来的消息 70 * @param session 可选的参数 71 */ 72 @OnMessage 73 public void onMessage(String message, Session session) { 74 String[] stringNum = message.split(","); 75 if(stringNum[0].contains("em")&&stringNum[1].equals("kehu")){ 76 try { 77 String regEx="[^0-9]"; 78 Pattern p = Pattern.compile(regEx); 79 Matcher m = p.matcher(stringNum[0]); 80 List<customer> customerlist = customerUtil.getCustomerByOpenid(stringNum[2]);//这个是去数据库查找数据的。怎么存储数据等就看你们的性格 了。 81 String key = (String)webSocketSet.get("typeKefu"); 82 WebSocketTest c = (WebSocketTest)webSocketSet.get(key); 83 try { 84 c.session.getBasicRemote().sendText(m.replaceAll("").trim()+","+nickname+","+customerlist.get(0).getMobile()); 85 } catch (IOException e) { 86 webSocketSet.remove(c); 87 try { 88 c.session.close(); 89 } catch (IOException e1) { 90 // Ignore 91 } 92 try { 93 sendMessage("发送信息失败"); 94 } catch (IOException e1) { 95 // TODO Auto-generated catch block 96 e1.printStackTrace(); 97 } 98 } 99 } catch (Exception e2) { 100 // TODO Auto-generated catch block 101 e2.printStackTrace(); 102 } 103 }else{ 104 if(stringNum[1].equals("kehu")){ 105 try { 106 List<customer> customerlist = customerUtil.getCustomerByOpenid(stringNum[2]); 107 String key = (String)webSocketSet.get("typeKefu"); 108 WebSocketTest c = (WebSocketTest)webSocketSet.get(key); 109 try { 110 c.session.getBasicRemote().sendText(stringNum[0]+","+nickname+","+customerlist.get(0).getMobile()); 111 } catch (IOException e) { 112 webSocketSet.remove(c); 113 try { 114 c.session.close(); 115 } catch (IOException e1) { 116 // Ignore 117 } 118 try { 119 sendMessage("发送信息失败"); 120 } catch (IOException e1) { 121 // TODO Auto-generated catch block 122 e1.printStackTrace(); 123 } 124 } 125 } catch (Exception e2) { 126 // TODO Auto-generated catch block 127 e2.printStackTrace(); 128 } 129 }else{ 130 WebSocketTest c = (WebSocketTest)webSocketSet.get(stringNum[1]); 131 try { 132 c.session.getBasicRemote().sendText(stringNum[0]); 133 } catch (IOException e) { 134 webSocketSet.remove(c); 135 try { 136 c.session.close(); 137 } catch (IOException e1) { 138 // Ignore 139 } 140 try { 141 sendMessage("发送信息失败"); 142 } catch (IOException e1) { 143 // TODO Auto-generated catch block 144 e1.printStackTrace(); 145 } 146 } 147 } 148 } 149 150 //群发消息 151 System.out.println("来自客户端的消息:" + message); 152 /*for (String key : webSocketSet.keySet()) { 153 WebSocketTest client = null ; 154 try { 155 client = (WebSocketTest) webSocketSet.get(key); 156 synchronized (client) { 157 client.session.getBasicRemote().sendText(message); 158 } 159 } catch (IOException e) { 160 webSocketSet.remove(client); 161 try { 162 client.session.close(); 163 } catch (IOException e1) { 164 // Ignore 165 } 166 try { 167 sendMessage("发送信息失败"); 168 } catch (IOException e1) { 169 // TODO Auto-generated catch block 170 e1.printStackTrace(); 171 } 172 } 173 } */ 174 } 175 176 /** 177 * 发生错误时调用 178 * @param session 179 * @param error 180 */ 181 @OnError 182 public void onError(Session session, Throwable error){ 183 System.out.println("发生错误"); 184 error.printStackTrace(); 185 } 186 187 /** 188 * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。 189 * @param message 190 * @throws IOException 191 */ 192 public void sendMessage(String message) throws IOException{ 193 this.session.getBasicRemote().sendText(message); 194 //this.session.getAsyncRemote().sendText(message); 195 } 196 197 public static synchronized int getOnlineCount() { 198 return onlineCount; 199 } 200 201 public static synchronized void addOnlineCount() { 202 WebSocketTest.onlineCount++; 203 } 204 205 public static synchronized void subOnlineCount() { 206 WebSocketTest.onlineCount--; 207 } 208 }
信息返回到相应js到页面上。
效果图展示。