前言

不知大家在平时的需求中有没有遇到需要实时处理信息的情况,如站内信,订阅,聊天之类的。在这之前我们通常想到的方法一般都是采用轮训的方式每隔一定的时间向服务器发送请求从而获得最新的数据,但这样会浪费掉很多的资源并且也不是实时的,于是随着HTML5的推出带来了websocket可以根本的解决以上问题实现真正的实时传输。

websocket是什么?

至于websocket是什么、有什么用这样的问题一Google一大把,这里我就简要的说些websocket再本次实例中的作用吧。
由于在本次实例中需要实现的是一个聊天室,一个实时的聊天室。如下图:
1.gif

采用websocket之后可以让前端和和后端像C/S模式一样实时通信,不再需要每次单独发送请求。由于是基于H5的所以对于老的浏览器如IE7、IE8之类的就没办法了,不过H5是大势所趋这点不用担心。

后端

既然推出了websocket,作为现在主流的Java肯定也有相应的支持,所以在JavaEE7之后也对websocket做出了规范,所以本次的代码理论上是要运行在Java1.7+和Tomcat7.0+之上的。
看过我前面几篇文章的朋友应该都知道本次实例也是运行在之前的SSM之上的,所以这里就不再赘述了。
首先第一步需要加入websocket的依赖:

1 packagecom.css.tax.mobilebs.util;2
3 importjava.io.IOException;4 importjava.io.UnsupportedEncodingException;5 importjava.util.Date;6 importjava.util.HashMap;7 importjava.util.Iterator;8 importjava.util.Map;9 importjava.util.concurrent.CopyOnWriteArraySet;10
11 importjavax.websocket.OnClose;12 importjavax.websocket.OnError;13 importjavax.websocket.OnMessage;14 importjavax.websocket.OnOpen;15 importjavax.websocket.Session;16 importjavax.websocket.server.PathParam;17 importjavax.websocket.server.ServerEndpoint;18
19 importorg.g4studio.common.dao.Reader;20 importorg.g4studio.common.service.impl.BaseServiceImpl;21 importorg.g4studio.common.util.SpringBeanLoader;22 importorg.g4studio.common.web.BaseAction;23 importorg.g4studio.core.metatype.Dto;24 importorg.g4studio.core.metatype.impl.BaseDto;25 importorg.junit.Test;26
27 importcom.css.tax.mobilebs.Vo.CurrentUserVo;28 importcom.css.tax.mobilebs.serviceI.WebSocketService;29 importcom.css.tax.mobilebs.serviceI.ZjzzService;30
31 /**
32 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,33 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端34 */
35 @ServerEndpoint("/websocket/{user}/{id}/{ptbz}")36 public class WebSocket extendsBaseAction{37 //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
38 private static int onlineCount = 0;39 //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
40 private static CopyOnWriteArraySet<Map<String, WebSocket>> webSocketSet = new CopyOnWriteArraySet<Map<String, WebSocket>>();41 private static CopyOnWriteArraySet<Map<String, WebSocket>> webSocketSetPt = new CopyOnWriteArraySet<Map<String, WebSocket>>();42 private WebSocketService zjzzWebSocketService = (WebSocketService)super.getService("zjzzWebSocketService");43 //与某个客户端的连接会话,需要通过它来给客户端发送数据
44 privateSession session;45 private Map<String, WebSocket> webSocketMap = new HashMap<String, WebSocket>();46 private CurrentUserVo currentUserVo = newCurrentUserVo();47
48 /**
49 * 连接建立成功调用的方法50 *51 *@paramsession52 * 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据53 */
54 @OnOpen55 public void onOpen(@PathParam("user") String user,56 @PathParam("id") String id, @PathParam("ptbz") String ptbz,57 Session session) {58 String charset =getEncoding(user);59 try{60 byte[] b =user.getBytes(charset);61 user = new String(b, "utf-8");62 } catch(UnsupportedEncodingException e) {63 e.printStackTrace();64 }65 this.session =session;66 currentUserVo.setFbrmc(user);67 currentUserVo.setFbr(id);68 currentUserVo.setPtbz(ptbz);69 currentUserVo.setTwr_dm(id);70 currentUserVo.setPtbz(ptbz);71 webSocketMap.put(id, this);72 if("pt".equals(ptbz)) {73 currentUserVo.setZjmc(user);74 currentUserVo.setZjry_dm(id);75 currentUserVo.setKhdfwr(id);76 webSocketSetPt.add(webSocketMap);77 }else{78 currentUserVo.setNsrmc(user);79 webSocketSet.add(webSocketMap); //加入set中
80 }81 addOnlineCount(); //在线数加
82 System.out.println("有新连接加入!当前在线人数为" +getOnlineCount());83 }84
85 /**
86 * 连接关闭调用的方法87 */
88 @OnClose89 public voidonClose() {90 if("pt".equals(this.currentUserVo.getPtbz())) {91 webSocketSetPt.remove(this.webSocketMap);92 }else{93 webSocketSet.remove(this.webSocketMap); //从set中删除
94 }95 subOnlineCount(); //在线数减
96 System.out.println("有一连接关闭!当前在线人数为" +getOnlineCount());97 }98
99 /**
100 * 收到客户端消息后调用的方法101 *102 *@parammessage103 * 客户端发送过来的消息104 *@paramsession105 * 可选的参数106 */
107 @OnMessage108 public voidonMessage(String message,Session session) {109 boolean boo = false;110
111 System.out.println("来自" + currentUserVo.getFbrmc() + "的消息:" + message+",发向"+currentUserVo.getJsr_dm());112 //判断是否为未读消息
113 int a = message.indexOf("&&&");114 System.out.println(a);115 if(a!=-1) {//为未读消息
116 String[] msgStr = message.split("&&&");117 String userMes = msgStr[0];118 String[] user = userMes.split("@");119 String uuid = "";120 String wdjsr = "";121 String fbrmc = "";122 String fbr = "";123 String zjzzuuid = "";124 if(user.length>0) {125 wdjsr = user[0];126 uuid = user[1];127 fbrmc = user[2];128 fbr = user[3];129 zjzzuuid = user[4];130 }131 message = msgStr[1];132 CopyOnWriteArraySet<Map<String, WebSocket>> websocketSet = null;133 if("pt".equals(this.currentUserVo.getPtbz())) {134 websocketSet =webSocketSetPt;135 }else{136 websocketSet =webSocketSet;137 }138 if(!"everybody".equals(wdjsr)) {139 //消息有指定平台用户
140 for (Map<String, WebSocket>itemMap : websocketSet) {141 WebSocket socket =itemMap.get(wdjsr);142 if(socket!=null) {143 try{144 if("pt".equals(this.currentUserVo.getPtbz())) {145 socket.sendMessage(fbr+"@@"+fbrmc + "@^&" +message);146 socket.currentUserVo.setKhdfwr(this.currentUserVo.getFbr());147 }else{148 socket.sendMessage(fbrmc + "@^&" +message);149 socket.currentUserVo.setKhdfwr(fbr);150 }151 socket.currentUserVo.setJsr_dm(fbr);//设置该对话的接收人代码
152 socket.currentUserVo.setJsr(fbrmc);153 socket.currentUserVo.setZjzzuuid(zjzzuuid);154 boo = true;155 Dto reDto = newBaseDto();156 reDto.put("uuid", uuid);157 reDto.put("ckbz", "Y");158 reDto.put("xgr_dm", "111");159 reDto.put("xgsj", SystemUtils.dateFormat(newDate()));160 zjzzWebSocketService.updateLtxxDatas(reDto);161 } catch(IOException e) {162 e.printStackTrace();163 }164 }165 }166 }else{167 //未读消息没有指定平台用户
168 if("pt".equals(this.currentUserVo.getPtbz())) {169 Object[] objArr =webSocketSetPt.toArray();170 int index = (int) (Math.random() *objArr.length);171 Map<String, WebSocket> map = (Map<String, WebSocket>) objArr[index];172 for(WebSocket socket : map.values()) {173 if(socket!=null) {174 try{175 boo = true;176 socket.sendMessage(fbr+"@@"+fbrmc + "@^&" +message);177 socket.currentUserVo.setZjzzuuid(zjzzuuid);178 socket.currentUserVo.setJsr_dm(fbr);179 socket.currentUserVo.setJsr(fbrmc);180 socket.currentUserVo.setKhdfwr(socket.currentUserVo.getFbr());181 //修改未读对话记录
182 Dto reDto = newBaseDto();183 reDto.put("uuid", uuid);184 reDto.put("jsr", this.currentUserVo.getFbr());185 reDto.put("ckbz", "Y");186 reDto.put("khdfwr", this.currentUserVo.getKhdfwr());187 reDto.put("xgr_dm", "111");188 reDto.put("xgsj", SystemUtils.dateFormat(newDate()));189 zjzzWebSocketService.updateWdWzdDatas(reDto);190 } catch(IOException e) {191 e.printStackTrace();192 continue;193 }194 }195 }196 }197 }198 }else{199 String[] xxArr = message.split("@@");200 String bz = "";201 String zjzzuuid = "";202 String fsmessage = "";203 String jsr = "";204 if(!"pt".equals(this.currentUserVo.getPtbz())) {205 String userXx = xxArr[0];206 String[] user = userXx.split("&&");207 bz = user[0];208 zjzzuuid = user[1];209 this.currentUserVo.setZjzzuuid(zjzzuuid);210 fsmessage = xxArr[1];211 }else{212 String[] xx = message.split("&@");213 jsr = xx[0];214 fsmessage = xx[1];215 }216 if("pt".equals(this.currentUserVo.getPtbz())) {217 if(jsr!=null&&jsr.length()>0) {218 //平台发送消息,发向指定客户端
219 boolean pdboo = false;220 for (Map<String, WebSocket>itemMap : webSocketSet) {221 WebSocket socket =itemMap.get(jsr);222 if(socket!=null) {223 try{224 boo = true;225 pdboo = true;226 socket.sendMessage(currentUserVo.getFbrmc() + "@^&" +fsmessage);227 //this.currentUserVo.setJsr_dm(socket.currentUserVo.getFbr());228 //this.currentUserVo.setJsr(socket.currentUserVo.getFbrmc());229 //存储已查看对话信息
230 if(socket.currentUserVo.getZjzzuuid()==null) {231 socket.currentUserVo.setZjzzuuid(this.currentUserVo.getZjzzuuid());232 }233 saveYckMessage(socket.currentUserVo.getZjzzuuid(),"Y",fsmessage,"Y",jsr);234 } catch(IOException e) {235 e.printStackTrace();236 continue;237 }238 }239 }240 if(!pdboo) {241 this.currentUserVo.setJsr_dm(jsr);242 String uuid =zjzzWebSocketService.queryZjzzuuidByJsr(jsr);243 this.currentUserVo.setZjzzuuid(uuid);244 boo = true;245 saveYckMessage(uuid,"Y",fsmessage,"N",this.currentUserVo.getJsr_dm());246 }247 }248 }else{249 if(this.currentUserVo.getJsr_dm()!=null&&this.currentUserVo.getJsr_dm().length()>0) {250 //该客户端消息已有接收对象,顺利发送给平台
251 for (Map<String, WebSocket>itemMap : webSocketSetPt) {252 WebSocket socket =itemMap.get(currentUserVo.getJsr_dm());253 if(socket!=null) {254 try{255 boo = true;256 socket.sendMessage(currentUserVo.getFbr()+"@@"+currentUserVo.getFbrmc() + "@^&" +fsmessage);257 //存储已查看对话信息
258 saveYckMessage(zjzzuuid,bz,fsmessage,"Y",this.currentUserVo.getJsr_dm());259 } catch(IOException e) {260 e.printStackTrace();261 continue;262 }263 }264 }265 }else{266 //该客户端尚未有接收对象,需要随机指定接收对象,并连接发送消息
267 if(webSocketSetPt.size()>0){268 //平台有用户连接
269 Object[] objArr =webSocketSetPt.toArray();270 int index = (int) (Math.random() *objArr.length);271 Map<String, WebSocket> map = (Map<String, WebSocket>) objArr[index];272 for(WebSocket socket : map.values()) {273 if(socket!=null) {274 try{275 boo = true;276 socket.sendMessage(currentUserVo.getFbr()+"@@"+currentUserVo.getFbrmc() + "@^&" +fsmessage);277 socket.currentUserVo.setJsr_dm(this.currentUserVo.getFbr());278 socket.currentUserVo.setJsr(this.currentUserVo.getFbrmc());279 this.currentUserVo.setKhdfwr(socket.currentUserVo.getFbr());280 this.currentUserVo.setJsr_dm(socket.currentUserVo.getFbr());281 this.currentUserVo.setZjry_dm(socket.currentUserVo.getFbr());282 this.currentUserVo.setZjmc(socket.currentUserVo.getFbrmc());283 this.currentUserVo.setJsr(socket.currentUserVo.getFbrmc());284 //存储已查看对话信息
285 saveYckMessage(zjzzuuid,bz,fsmessage,"Y",this.currentUserVo.getJsr_dm());286 } catch(IOException e) {287 e.printStackTrace();288 continue;289 }290 }291 }292 }else{293 try{294 this.sendMessage("系统:消息已发送,但当前未有服务人员链接,无法为您解答疑问!");295 //平台没有用户连接,无法发送消息,保存数据为所有人可接收的未读消息
296 this.currentUserVo.setJsr_dm("everybody");297 this.currentUserVo.setZjry_dm("everybody");298 this.currentUserVo.setKhdfwr("everybody");299 saveYckMessage(zjzzuuid,bz,fsmessage,"N",this.currentUserVo.getJsr_dm());300 boo = true;301 } catch(IOException e) {302 e.printStackTrace();303 }304 }305 }306 }307
308 }309 if(!boo){310 if(this.currentUserVo.getJsr_dm()!=null&&this.currentUserVo.getZjzzuuid()!=null) {311 if("pt".equals(this.currentUserVo.getPtbz())) {312 saveYckMessage(this.currentUserVo.getZjzzuuid(),"Y",message,"N",this.currentUserVo.getJsr_dm());313 }else{314 //存储未查看对话信息
315 String[] xxArr = message.split("@@");316 String userXx = xxArr[0];317 String[] user = userXx.split("&&");318 String bz = user[0];319 String zjzzuuid = user[1];320 String fsmessage = xxArr[1];321 saveYckMessage(zjzzuuid,bz,fsmessage,"N",this.currentUserVo.getJsr_dm());322 }323 }else{324 try{325 this.sendMessage("系统:消息未发出,可能是连接失败!请重新连接");326 } catch(IOException e) {327 e.printStackTrace();328 }329 }330 }331 }332
333 /**
334 *335 *@paramzjzzuuid    对话组uuid336 *@parambz    是否存在对话组标志337 *@parammessage    对话信息338 *@paramckbz    对话是否查看标志339 */
340 private voidsaveYckMessage(String zjzzuuid,String bz,String message,String ckbz,String jsr) {341 Dto dto = newBaseDto();342 String fbrmc =currentUserVo.getFbrmc();343 String fbr =currentUserVo.getFbr();344 String khdfwr =currentUserVo.getKhdfwr();345 if("N".equals(bz)) {//是否有uuid,判断其在数据库中是否存在已有信息346 //数据库没有该对话记录,故需创建对话记录
347 dto.put("uuid", zjzzuuid);348 //以下需前台传值
349 dto.put("twr_dm", currentUserVo.getTwr_dm());350 dto.put("nsrsbh", currentUserVo.getNsrsbh());351 dto.put("nsrmc", currentUserVo.getNsrmc());352 dto.put("zjmc", currentUserVo.getZjmc());353 dto.put("zjry_dm", currentUserVo.getZjry_dm());354 dto.put("fbr", fbr);355 dto.put("fbrmc", fbrmc);356 dto.put("jsr", jsr);357 dto.put("lrr_dm", fbr);358 dto.put("lrrq", SystemUtils.dateFormat(newDate()));359 zjzzWebSocketService.insertZjzzDhjl(dto);360
361 Dto dto1 = newBaseDto();362 dto1.put("lrr_dm", fbr);363 dto1.put("lrrq", SystemUtils.dateFormat(newDate()));364 dto1.put("uuid", SystemUtils.genUUID());365 dto1.put("zjzzuuid", zjzzuuid);366 dto1.put("dhnr", message);367 dto1.put("dhsj", SystemUtils.dateFormat(newDate()));368 dto1.put("fbr", fbr);369 dto1.put("ckbz", ckbz);370 dto1.put("khdfwr", khdfwr);371 dto1.put("fbrmc", fbrmc);372 dto1.put("jsr", jsr);373 zjzzWebSocketService.insertZjzzMxDhjlByUuid(dto1);374 }else{375 Dto redto = newBaseDto();376 redto.put("lrr_dm", fbr);377 redto.put("lrrq", SystemUtils.dateFormat(newDate()));378 redto.put("uuid", SystemUtils.genUUID());379 redto.put("zjzzuuid", zjzzuuid);380 redto.put("dhnr", message);381 redto.put("dhsj", SystemUtils.dateFormat(newDate()));382 redto.put("fbr", fbr);383 redto.put("ckbz", ckbz);384 redto.put("khdfwr", khdfwr);385 redto.put("fbrmc", fbrmc);386 redto.put("jsr", jsr);387 zjzzWebSocketService.insertZjzzMxDhjlByUuid(redto);388 }389 }390
391 /**
392 * 发生错误时调用393 *394 *@paramsession395 *@paramerror396 */
397 @OnError398 public voidonError(Session session, Throwable error) {399 System.out.println("发生错误");400 error.printStackTrace();401 }402
403 /**
404 * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。405 *406 *@parammessage407 *@throwsIOException408 */
409 public void sendMessage(String message) throwsIOException {410 this.session.getBasicRemote().sendText(message);411 //this.session.getAsyncRemote().sendText(message);
412 }413
414 public static synchronized intgetOnlineCount() {415 returnonlineCount;416 }417
418 public static synchronized voidaddOnlineCount() {419 WebSocket.onlineCount++;420 }421
422 public static synchronized voidsubOnlineCount() {423 WebSocket.onlineCount--;424 }425
426 public staticString getEncoding(String str) {427 String encode = "GB2312";428 try{429 if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是GB2312
430 String s =encode;431 return s; //是的话,返回GB2312,以下代码同理
432 }433 } catch(Exception e) {434 e.printStackTrace();435 }436 encode = "ISO-8859-1";437 try{438 if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是ISO-8859-1
439 String s1 =encode;440 returns1;441 }442 } catch(Exception e) {443 e.printStackTrace();444 }445 encode = "UTF-8";446 try{447 if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是UTF-8编码
448 String s2 =encode;449 returns2;450 }451 } catch(Exception e) {452 e.printStackTrace();453 }454 encode = "GBK";455 try{456 if (str.equals(new String(str.getBytes(encode), encode))) { //判断是不是GBK
457 String s3 =encode;458 returns3;459 }460 } catch(Exception e) {461 e.printStackTrace();462 }463 return ""; //到这一步,你就应该检查是不是其他编码啦
464 }465 }

这就是整个websocket的后端代码。看起来也比较简单主要就是使用那几个注解。每当有一个客户端连入、关闭、发送消息都会调用各自注解的方法。这里我讲一下sendMessage()这个方法。

websocket绕坑

sendMessage()方法中我只想实现一个简单的功能,就是将每次的聊天记录都存到数据库中。看似一个简单的功能硬是花了我半天的时间。
我先是按照以前的惯性思维只需要在这个类中注入service即可。但是无论怎么弄每次都注入不进来都是null
最后没办法只有google了,最后终于在神级社区StackOverFlow中找到了答案,就是前边所说的需要添加的第二个 maven依赖,然后加入@ServerEndpoint(value = "/websocket",configurator = SpringConfigurator.class)这个注解即可利用Spring注入了。接着就可以做消息的保存了。

前端

前端我采用了Ext.js做的。还是先贴一下代码:

zxws_main.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <metacharset="UTF-8">
5 <title>Parent Page</title>
6 <linkrel="stylesheet"type="text/css"href="css/Globle.css" />
7 <linkrel="stylesheet"type="text/css"href="css/index.css" />
8 <scriptsrc="js/jquery-1.12.0.min.js"type="text/javascript"
9 charset="utf-8"></script>
10 <styletype="text/css">
11 #main_left div{
12 background:#D1D1D1;
13 border-bottom:1px #DDDDDD solid;
14 }
15
16 #main_left input{
17 font-size:14px;
18 text-align:center;
19 height:40px;
20 width:150px;
21 line-height:40px;
22 color:white;
23 }
24
25 #main_left span{
26 background:red none repeat scroll 0 0;
27 border-radius:9px;
28 display:inline-block;
29 height:18px;
30 line-height:18px;
31 width:18px;
32 text-align:center;
33 color:white;
34 display:none;
35
36 }
37
38 #add{
39 position:absolute;
40 bottom:200px;
41 }
42 .butt{
43 height:30px;
44 width:40px;
45 margin-top:80px;
46 margin-left:-391px;
47 display:inline-block;
48 }
49 </style>
50 </head>
51 <body>
52     <buttonclass="butt"type="button"class="fs"onclick="()">清理</button>
53     <divid="main">
54         <divid="main_left">
55             <!--<h1>This is the Parent Page.</h1>-->
56
57         </div>
58         <divid="main_right">
59             <iframestyle="width: 600px; height: 540px;"id="childframe"
60 name="childframe"src="zxws.jsp"></iframe>
61         </div>
62     </div>
63     <scripttype="text/javascript"src="js/map.js"></script>
64
65 </body>
66 <scripttype="text/javascript"src="zxws_main.js"></script>
67 </html>

zxws_main.js
1 /**
2 * Created by wanglei on 2017-07-03.3  */
4 var user = GetQueryString("user");5 var id = GetQueryString("id");6 var ptbz = GetQueryString("ptbz");//客户端为:khd;平台为:pt;
7 var uuid = "";8 var websocket = null;9 var jsonStr = localStorage.getItem('WSBS_PT_ZXBS_'+id);10 var jsonObj2;11 var userOnLineMap = newMap();12 function GetQueryString(name) {13     var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");14     var r = decodeURI(window.location.search).substr(1).match(reg);15     if (r != null)16         return unescape(r[2]);17     return null;18 }19 var zxwin =window;20 var parentWin;21 //定义最后光标对象
22
23 var lastEditRange, selection;24 //判断当前浏览器是否支持WebSocket
25 if ('WebSocket'in window) {26     websocket = new WebSocket("ws://222.90.69.254:7001/mobile/websocket/"
27             + user+"/"+id+"/"+ptbz);28 } else{29     alert('当前浏览器 Not support websocket,请更换浏览器');30 }31 //连接发生错误的回调方法
32 websocket.onerror =function() {33     setMessageInnerHTML("WebSocket连接发生错误");34 };35 //连接成功建立的回调方法
36 websocket.onopen =function(aa) {37     //setMessageInnerHTML("WebSocket连接成功");38     //查看是否有未读消息,并发送消息
39     if(jsonStr==null||jsonStr.length==0||jsonStr=="{}") {40         jsonObj2 ={};41         var o = document.getElementById("main_right");42         o.style.visibility="hidden";43     }else{44         jsonObj2 =JSON.parse(jsonStr);45         //document.getElementById("main_right").innerHTML = "<iframe style='width:600px; height:540px;' id='childframe' name='childframe' src='zxws.jsp'></iframe>";
46 }47 $.ajax({48         method:"POST",49 data:{50             "twr_dm":id,51             "ptbz":ptbz52 },53         url:"../zjzz.do?reqCode=initDhxx",54 success: function(msg){55             var datareq = eval('(' + msg + ')');56             if(msg!=null&&msg!='[]'){57                 //debugger;
58                 if("pt"!=ptbz) {59                     uuid =datareq.uuid;60                     document.getElementById("uuid").setAttribute("uuid", datareq.uuid);61                     bz =datareq.bz;62                     document.getElementById("uuid").setAttribute("bz", datareq.bz);63 }64 $.ajax({65                     method:"POST",66 data : {67                         //"zjzzuuid" : document.getElementById("uuid").getAttribute("uuid"),
68                         "jsr": id69 },70                     url:"../zjzz.do?reqCode=queryLtxxDatas",71 success: function(msg){72                         //debugger;73                         //初始化历史聊天记录
74                         var json =eval(jsonObj2);75                         //localStorage.removeItem('WSBS_PT_ZXBS_'+id);
76                         var a = 1;77                         if(jsonStr!=null&&jsonStr.length>0) {78                             for(var prop in json)79 {80                                 var userArray = prop.split("@");81                                 var jsrid = userArray[0];82                                 var jsrmc = userArray[1];83                                 //alert(jsrid+"~~"+jsrmc);
84                                 if(jsrmc!=undefined&&jsrmc!=null&&jsrmc.length>0) {85 userOnLineMap.put(jsrid, jsrmc);86                                     $("#main_left").append("<div><input id='"+jsrid+"'/><span id='"+jsrid+"_span'></span></div>");87                                     $("#"+jsrid).attr("value",jsrmc);88                                     $("#"+jsrid).attr("type","button");89                                     $("#"+jsrid).attr("onclick","btnClick('"+jsrid+"')");90                                     if(a==1) {91                                         var jsrMsg =jsonObj2[prop];92                                         var obj = window.frames["childframe"].document;93                                         //debugger;
94                                         window.frames["childframe"].document.getElementById("uuid").setAttribute("bz", "Y");95                                         window.frames["childframe"].document.getElementById("uuid").setAttribute("fsrid",jsrid);96                                         window.frames["childframe"].document.getElementById("uuid").setAttribute("fsrmc",jsrmc);97                                         for (var i = 0; i < jsrMsg.length; i++) {98                                             var fsr =jsrMsg[i].fsr;99                                             if(fsr==jsrid) {100                                                 var c1 = obj.getElementById("dhk");101                                                 var div1 = obj.createElement("div");102                                                 div1.className = "org_div";103
104                                                 /*var now = new Date();105 var nowTime = now.toLocaleString();106 var date = nowTime.substring(0,10);//截取日期107 var time = nowTime.substring(10,20);*/
108
109                                                 var yhDiv = obj.createElement("span");110                                                 yhDiv.className = "org_yh1";111                                                 yhDiv.innerHTML = jsrMsg[i].fsrmc+":";112                                                 var newDiv = obj.createElement("p");113                                                 newDiv.className = "org_box";114                                                 newDiv.innerHTML =jsrMsg[i].dhnr;115                                                 var sjDiv = document.createElement("p");116                                                 sjDiv.className = "org_sj2";117                                                 sjDiv.innerHTML =jsrMsg[i].lrrq;118                                                 //var lrrq = time;119                                                 //sjDiv.innerHTML = lrrq;
120 div1.appendChild(yhDiv);121 div1.appendChild(newDiv);122 div1.appendChild(sjDiv);123 c1.appendChild(div1);124                                             }else{125                                                 var c1 = obj.getElementById("dhk");126                                                 var div1 = obj.createElement("div");127                                                 div1.className = "org_div";128
129                                                 /*var now = new Date();130 var nowTime = now.toLocaleString();131 var date = nowTime.substring(0,10);//截取日期132 var time = nowTime.substring(10,20);*/
133
134                                                 var yhDiv = obj.createElement("span");135                                                 yhDiv.className = "org_yh";136                                                 yhDiv.innerHTML = ":我";137                                                 var newDiv = obj.createElement("p");138                                                 newDiv.className = "org_hf";139                                                 newDiv.innerHTML =jsrMsg[i].dhnr;140                                                 var sjDiv = document.createElement("p");141                                                 sjDiv.className = "org_sj1";142                                                 //var lrrq = time;143                                                 //sjDiv.innerHTML = lrrq;
144                                                 sjDiv.innerHTML =jsrMsg[i].lrrq;145 div1.appendChild(yhDiv);146 div1.appendChild(newDiv);147 div1.appendChild(sjDiv);148 c1.appendChild(div1);149                                                 c1.scrollTop =c1.scrollHeight;150 }151 }152 }153                                     a = a+1;154 }155 }156 }157                         if(msg!=null){158                             var datareq = eval('(' + msg + ')');159                             for ( var int = 0; int < datareq.length; int++) {160                                 var msg = datareq[int].dhnr;161                                 var dhuuid = datareq[int].uuid;162                                 var wdjsr = datareq[int].jsr;163                                 var fbrmc = datareq[int].fbrmc;164                                 var fbr = datareq[int].fbr;165                                 var zjzzuuid = '';166                                 if("pt"!=ptbz) {167                                     zjzzuuid = document.getElementById("uuid").getAttribute("uuid");168                                 }else{169                                     zjzzuuid = datareq[int].zjzzuuid;170 }171                                 websocket.send(wdjsr+"@"+dhuuid+"@"+fbrmc+"@"+fbr+"@"+zjzzuuid+"&&&"+msg);172 }173 }174 }175 });176 }177 }178 });179 }180 //接收到消息的回调方法
181 websocket.onmessage =function(event) {182 debugger;183     var o = document.getElementById("main_right");184     if(o.style.visibility=="hidden") {185         o.style.visibility="visible";186         //document.getElementById("main_right").innerHTML = "<iframe style='width:600px; height:540px;' id='childframe' name='childframe' src='zxws.jsp'></iframe>";
187 }188     var mes =event.data;189     var msg = "";190     var jsr = "";191     if(ptbz=='pt') {192         var arr = mes.split('@@');193         jsr = arr[0];//设置当前tab的id,即接收人
194         msg = arr[1];195     }else{196         msg=mes;197 }198     var fsrArr = msg.split('@^&');199     var fsr = fsrArr[0];200     msg = fsrArr[1];201     var xxUser =userOnLineMap.get(jsr);202 debugger;203     if(xxUser!=undefined && xxUser.length>0) {204
205     }else{206 userOnLineMap.put(jsr, fsr);207         $("#main_left").append("<div><input id='"+jsr+"'/><span id='"+jsr+"_span'></span></div>");208         $("#"+jsr).attr("value",fsr);209         $("#"+jsr).attr("type","button");210         $("#"+jsr).attr("onclick","btnClick('"+jsr+"')");211 }212     if (fsr !=user) {213         var obj = window.frames["childframe"].document.getElementById("uuid");214         if(obj.getAttribute("fsrid")!=undefined&&obj.getAttribute("fsrid")!=jsr) {215             var num = document.getElementById(jsr+"_span").innerHTML;216             if(num==null) {217                 num=0;218 }219             var num1 = num-0+1;220             document.getElementById(jsr+"_span").innerHTML=num1;221             if(num1>0){222                 document.getElementById(jsr+"_span").style.display='inline-block';223 }224             //如果是新用户进来得先走这步,所以再这里就要给它加上日期,如果是老用户的话直接跳到else里去执行了,走到发送里面在给加日期
225             var now = newDate();226             var lrrq =now.toLocaleString();227             var date = lrrq.substring(0,10);//截取日期
228             var time = lrrq.substring(10,20);229
230             var dataJson = {'fsr':jsr,'jsr':id,'fsrmc':fsr,'dhnr':msg,'lrrq':lrrq};231             document.getElementById("childframe").contentWindow.updateLocalStorage(jsr,fsr,dataJson);232         }else{233             obj.setAttribute("fsrid",jsr);234             obj.setAttribute("fsrmc",fsr);235 }236         if(obj.getAttribute("bz")==undefined){237             //debugger;
238 btnClick(jsr);239 }240         obj.setAttribute("bz","Y");241         document.getElementById("childframe").contentWindow.hfxx(jsr,fsr,msg);242 }243 }244
245 function btnClick(jsr){246     //alert(JSON.stringify(jsonObj2));247     //debugger;
248     document.getElementById(jsr+"_span").style.display='none';249     document.getElementById(jsr+"_span").innerHTML='';250     window.frames["childframe"].document.getElementById("dhk").innerHTML = '';251     localStorage.setItem('WSBS_PT_ZXBS_'+id, JSON.stringify(jsonObj2));252     window.frames["childframe"].document.getElementById("uuid").setAttribute("fsrid",jsr);253     window.frames["childframe"].document.getElementById("uuid").setAttribute("fsrmc",userOnLineMap.get(jsr));254     document.getElementById("childframe").contentWindow.initLocalStorage(jsr,id);255
256     //alert(window.frames["childframe"].document.getElementById("uuid").getAttribute("fsrid"));
257 }258
259 //连接关闭的回调方法
260 websocket.onclose =function() {261     localStorage.setItem('WSBS_PT_ZXBS_'+id, JSON.stringify(jsonObj2));262     //localStorage.removeItem('WSBS_PT_ZXBS_'+id);263     //setMessageInnerHTML("WebSocket连接关闭");
264 }265
266 //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
267 window.onbeforeunload =function() {268 closeWebSocket();269 }270
271 //关闭WebSocket连接
272 function closeWebSocket() {273 websocket.close();274 }275
276 function send(data) {//获取当前tab的id,即接收人
277 websocket.send(data);278 }其实其中重要的就是那几个JS方法,都写有注释。需要注意的是这里
1 //判断当前浏览器是否支持WebSocket
2 if ('WebSocket'in window) {3     websocket = new WebSocket("ws://222.90.69.254:7001/mobile/websocket/"
4             + user+"/"+id+"/"+ptbz);5 } else{6     alert('当前浏览器 Not support websocket,请更换浏览器');7 }

zxws.jsp

<%@ page language="java"contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<htmllang="en">
<head>
<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">
<metaname="viewport"content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
<title>在线问税</title>
</head>
<scripttype="text/javascript"src="../zjzz/js/jquery-1.12.0.min.js"charset="utf-8"></script>
<scripttype="text/javascript"src="zxws.js"charset="utf-8"></script>
<style>.org_box{float:left;text-align:left;font-family:"Microsoft YaHei", 微软雅黑;font-size:16px;margin-top:5px;height:auto;width:auto;max-width:55%;line-height:30px;border:1px solid #E3E3E3;background:#F6F6F6;border-radius:4px;padding:5px;display:inline-block;
}.org_div{margin-top:8px;float:right;width:100%;word-break:break-all;
}.org_hf{float:right;border:1px solid #87CEEB;background:#ACD9F8;border-radius:4px;padding:5px;height:auto;width:auto;line-height:30px;max-width:55%;word-break:break-all;display:inline-block;overflow:hidden;text-align:left;
}.org_yh{float:right;height:20px;word-break:break-all;
}.org_yh1{margin-top:10px;float:left;height:auto;width:auto;word-break:break-all;
}.org_sj1{float:right;height:5px;font-size:8px;word-break:break-all;text-align:left;border-radius:4px;padding:5px;margin-top:0px;
}.org_sj2{float:left;height:5px;font-size:8px;word-break:break-all;text-align:left;border-radius:4px;padding:0px;margin-top:9px;
}*{margin:0px;padding:0px;list-style:none;box-sizing:border-box;
}#zt{height:516px;
}#dhk{margin-top:2px;height:300px;width:590px;overflow-Y:auto;border:1px solid #e7eaf1;margin-left:5px;margin-right:5px;
}#lts{height:160px;overflow:auto;border:1px solid #e7eaf1;margin-left:5px;margin-right:5px;
}#gjl{height:20%;overflow:auto;
}#ltk{height:79.5%;overflow:auto;border:1px solid #e7eaf1;display:block;visibility:visible;
}.close{position:absolute;top:5px;right:5px;z-index:1000;width:19px;height:19px;cursor:pointer;-webkit-user-select:none;
}.minisize{position:absolute;right:38px;top:4px;z-index:1000;width:19px;height:19px;cursor:pointer;-webkit-user-select:none;
}.fs{margin-left:500px;;background:#0f88eb;width:75px;color:#fff;border:1px solid #0f88eb;cursor:pointer;display:inline-block;font-size:14px;line-height:32px;padding:0 16px;text-align:center;float:left;
}.qx{margin-left:20px;;background:#0f88eb;width:75px;color:#fff;border:1px solid #0f88eb;cursor:pointer;display:inline-block;font-size:14px;line-height:32px;padding:0 16px;text-align:center;float:left;
}#bqb{position:absolute;width:250px;border:1px solid #e7eaf1;left:30px;top:300px;visibility:hidden;
}
</style><body><!--<button type="button" class="fs" οnclick="localStorage.removeItem('WSBS_PT_ZXBS_'+id);" id=" ">清理</button>--><divid="zt"><divid="bqb"><imgsrc="biaoqing/1.png"style="width: 27px; height: 27px;"onclick="bqdj(1);" /> <imgsrc="biaoqing/2.png"style="width: 27px; height: 27px;"onclick="bqdj(2);" /> <imgsrc="biaoqing/3.png"style="width: 27px; height: 27px;"onclick="bqdj(3);" /> <imgsrc="biaoqing/4.png"style="width: 27px; height: 27px;"onclick="bqdj(4);" /> <imgsrc="biaoqing/5.png"style="width: 27px; height: 27px;"onclick="bqdj(5);" /> <imgsrc="biaoqing/6.png"style="width: 27px; height: 27px;"onclick="bqdj(6);" /></div><divid="dhk"style="background: #EEEEEE"></div><divid="lts"><divid="gjl"><ul><li><imgonclick="tjbq()"src="picture/1.png"style="width: 27px; height: 27px; margin-left: 5px; margin-left: 5px;" /></li></ul></div><divid="ltk"contenteditable="true" ></div></div><divstyle="margin-top: 3px;"><!--<span id="subjectchk">还可输入 <strong id="checklen"style="color: #FF0000">400</strong> 个字符</span>--><buttontype="button"class="fs"onclick="fsxx();"id="uuid">发送</button><!--<button type="button" class="qx" οnclick="closewindow();">关闭</button>--></div></div></body>
</html>

zxws.js
1 function fsxx() {2     var c = document.getElementById("ltk").innerHTML;3     var jsr = document.getElementById("uuid").getAttribute("fsrid");4     var fsrmc = document.getElementById("uuid").getAttribute("fsrmc");5
6     var now = newDate();7     var nowTime =now.toLocaleString();8     var date = nowTime.substring(0,10);//截取日期
9     var time = nowTime.substring(10,20);10
11     //var date = new Date();12     //var year = date.getFullYear();13     //var month = date.getMonth()+1;14     //var day = date.getDate();15     //var hour = date.getHours();16     //var minute = date.getMinutes();17     //var second = date.getSeconds();18     //alert(year+'年'+month+'月'+day+'日'+hour+':'+minute+':'+second);
19
20     window.parent.send(jsr+"&@"+c);21     var c1 = document.getElementById("dhk");22     var div1 = document.createElement("div");23     div1.className = "org_div";24     var yhDiv = document.createElement("span");25     yhDiv.className = "org_yh";26     yhDiv.innerHTML = ":我";27     var newDiv = document.createElement("span");28     newDiv.className = "org_hf";29     var msg =c ;30     newDiv.innerHTML =msg;31     var sjDiv = document.createElement("span");32     sjDiv.className = "org_sj1";33     var lrrq =nowTime;34     sjDiv.innerHTML =lrrq;35     var dataJson = {'fsr':window.parent.id,'jsr':jsr,'fsrmc':fsrmc,'dhnr':c,'lrrq':lrrq};36 updateLocalStorage(jsr,fsrmc,dataJson);37 div1.appendChild(yhDiv);38 div1.appendChild(newDiv);39 div1.appendChild(sjDiv);40 c1.appendChild(div1);41     /*var c2 = document.createElement("br");42 c1.appendChild(c2);*/
43     document.getElementById("ltk").innerHTML = "";44     c1.scrollTop =c1.scrollHeight;45 }46 function hfxx(jsr,fsr,data) {47     var a = document.getElementById("uuid").getAttribute("fsrid");48     var fsrmc = document.getElementById("uuid").getAttribute("fsrmc");49     //var d = document.getElementById("time").innerHTML;
50
51     var now = newDate();52     var nowTime =now.toLocaleString();53     var date = nowTime.substring(0,10);//截取日期
54     var time = nowTime.substring(10,20);55     //var date = new Date();56     //var year = date.getFullYear();57     //var month = date.getMonth()+1;58     //var day = date.getDate();59     //var hour = date.getHours();60     //var minute = date.getMinutes();61     //var second = date.getSeconds();62     //alert(year+'年'+month+'月'+day+'日'+hour+':'+minute+':'+second);
63
64     if(a==jsr) {65         var c1 = document.getElementById("dhk");66         var div1 = document.createElement("div");67         div1.className = "org_div";68         var yhDiv = document.createElement("span");69         yhDiv.className = "org_yh1";70         yhDiv.innerHTML = fsr+":";71         var newDiv = document.createElement("span");72         newDiv.className = "org_box";73         newDiv.innerHTML =data;74         var sjDiv = document.createElement("span");75         sjDiv.className = "org_sj2";76         var lrrq =nowTime;77         sjDiv.innerHTML =lrrq;78 div1.appendChild(yhDiv);79 div1.appendChild(newDiv);80 div1.appendChild(sjDiv);81 c1.appendChild(div1);82         /*var c2 = document.createElement("br");83 c1.appendChild(c2);*/
84         c1.scrollTop =c1.scrollHeight;85         var dataJson = {'fsr':a,'jsr':window.parent.id,'fsrmc':fsr,'dhnr':data,'lrrq':lrrq};86 updateLocalStorage(a,fsrmc,dataJson);87     }else if(a=="系统"){88         var c1 = document.getElementById("dhk");89         var div1 = document.createElement("div");90         div1.className = "org_div";91         var newDiv = document.createElement("span");92         newDiv.className = "org_box";93         newDiv.innerHTML =data;94 div1.appendChild(newDiv);95 c1.appendChild(div1);96         /*var c2 = document.createElement("br");97 c1.appendChild(c2);*/
98         c1.scrollTop =c1.scrollHeight;99 }100 }101 //更新对话json串
102 var jsonObj1 =window.parent.jsonObj2;103 function updateLocalStorage(jsr,fsr,data) {104     //debugger;
105     var str = jsr+"@"+fsr;106     if(jsonObj1[str]==undefined) {107         var temp =[];108         jsonObj1[str] =temp;109 jsonObj1[str].push(data);110     }else{111 jsonObj1[str].push(data);112 }113 }114 function initLocalStorage(jsr,id) {115     jsonObj1 =window.parent.jsonObj2;116     var fsrid = document.getElementById("uuid").getAttribute("fsrid");117     var fsrmc = document.getElementById("uuid").getAttribute("fsrmc");118     var str = fsrid+"@"+fsrmc;119     var jsonStr = localStorage.getItem('WSBS_PT_ZXBS_'+id);120     if(jsonStr==null||jsonStr.length==0) {121
122     }else{123         var jsonMsg =JSON.parse(jsonStr);124         if(jsonMsg[str]!=undefined) {125             var jsrMsg =jsonMsg[str];126             for (var i = 0; i < jsrMsg.length; i++) {127                 var fsr =jsrMsg[i].fsr;128                 if(fsr==fsrid) {129                     var c1 = document.getElementById("dhk");130                     var div1 = document.createElement("div");131                     div1.className = "org_div";132                     var yhDiv = document.createElement("span");133                     yhDiv.className = "org_yh1";134                     yhDiv.innerHTML = jsrMsg[i].fsrmc+":";135                     var newDiv = document.createElement("p");136                     newDiv.className = "org_box";137                     newDiv.innerHTML =jsrMsg[i].dhnr;138                     var sjDiv = document.createElement("span");139                     sjDiv.className = "org_sj2";140                     sjDiv.innerHTML =jsrMsg[i].lrrq;141 div1.appendChild(yhDiv);142 div1.appendChild(newDiv);143 div1.appendChild(sjDiv);144 c1.appendChild(div1);145                     c1.scrollTop =c1.scrollHeight;146                 }else{147                     var c1 = document.getElementById("dhk");148                     var div1 = document.createElement("div");149                     div1.className = "org_div";150                     var yhDiv = document.createElement("span");151                     yhDiv.className = "org_yh";152                     yhDiv.innerHTML = ":我";153                     var newDiv = document.createElement("p");154                     newDiv.className = "org_hf";155                     newDiv.innerHTML =jsrMsg[i].dhnr;156                     var sjDiv = document.createElement("span");157                     sjDiv.className = "org_sj1";158                     sjDiv.innerHTML =jsrMsg[i].lrrq;159 div1.appendChild(yhDiv);160 div1.appendChild(newDiv);161 div1.appendChild(sjDiv);162 c1.appendChild(div1);163                     c1.scrollTop =c1.scrollHeight;164 }165 }166 }167 }168 }169
170 function tjbq() {171     if(bqb.style.visibility=='visible'){172         bqb.style.visibility="hidden";173     }else{174         bqb.style.visibility="visible";175 }176 }177
178 function hiddenBq() {179     var bqb = document.getElementById("bqb");180     bqb.style.visibility = "hidden";181 }182
183 function bqdj(num) {184     var imgsrc = "biaoqing/" + num + ".png";185 showImg(imgsrc);186 hiddenBq();187 }188
189 function showImg(imgsrc) {190     var img = document.createElement("img");191     img.src =imgsrc;192     //img.onselectstart= function(){return false;}
193     var parent = document.getElementById("ltk");194     var div = document.createElement("div");195 div.appendChild(img);196     div.style.display = 'inline-block';197     div.onselectstart= function(){return false;}198 parent.appendChild(div);199 }200 function getByteLen(val) {201     var len = 0;202     for (var i = 0; i < val.length; i++) {203       var a =val.charAt(i);204       if (a.match(/[^\x00-\xff]/ig) != null) {205         len += 2;206 }207       else{208         len += 1;209 }210 }211     returnlen;212 }213   //只要键盘一抬起就验证编辑框中的文字长度,最大字符长度可以根据需要设定
214 function checkLength(obj) {215           var a = document.getElementById("ltk");216 debugger;217         var maxChars = 400;//最多字符数
218         var curr = maxChars -getByteLen(obj.innerHTML);219         if (curr > 0) {220           document.getElementById("checklen").innerHTML =curr.toString();221         } else{222           document.getElementById("checklen").innerHTML = '0';223           document.getElementById("ltk").readOnly = true;224           var oBtn = document.getElementById('fs');225           oBtn.onclick =function(){226               oBtn.disabled = 'disabled';227 };228 }229 }230
231   /**
232 * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。233 *234 *@parammessage235 *@throwsIOException236      */
237 function xxql() {238         this.session.getBasicRemote().sendText(message);239         /*if("pt".equals(this.currentUserVo.getPtbz())) {240 webSocketSetPt.remove(this.webSocketMap);241 }else{242 webSocketSet.remove(this.webSocketMap); // 从set中删除243 }244 subOnlineCount(); // 在线数减245 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());*/
246 }247   

注意:最后要在web-info下lib文件夹下引入websocket-api.jar,这样打war包才不会出错

转载于:https://www.cnblogs.com/wangxuemei/p/8417821.html

基于webSocket的聊天室相关推荐

  1. 基于WebSocket实现聊天室(Node)

    基于WebSocket实现聊天室(Node) WebSocket是基于TCP的长连接通信协议,服务端可以主动向前端传递数据,相比比AJAX轮询服务器,WebSocket采用监听的方式,减轻了服务器压力 ...

  2. java开发websocket聊天室_java实现基于websocket的聊天室

    [实例简介] java实现基于websocket的聊天室 [实例截图] [核心代码] chatMavenWebapp └── chat Maven Webapp ├── pom.xml ├── src ...

  3. SpringBoot + Vue 实现基于 WebSocket 的聊天室(单聊)

    前言 在前一篇文章SpringBoot 集成 STOMP 实现一对一聊天的两种方法中简单介绍了如何利用 STOMP 实现单聊,本文则将以一个比较完整的示例展示实际应用,不过本文并未使用 STOMP,而 ...

  4. SSM(五)基于webSocket的聊天室

    SSM(五)基于webSocket的聊天室 前言 不知大家在平时的需求中有没有遇到需要实时处理信息的情况,如站内信,订阅,聊天之类的.在这之前我们通常想到的方法一般都是采用轮训的方式每隔一定的时间向服 ...

  5. java websocket netty_用SpringBoot集成Netty开发一个基于WebSocket的聊天室

    前言 基于SpringBoot,借助Netty控制长链接,使用WebSocket协议做一个实时的聊天室. 项目效果 项目统一登录路径:http://localhost:8080/chat/netty ...

  6. 基于 WebSocket 的聊天室项目(下)

    1.创建一个聊天室的数据库 注意修改上一篇准备工作中写的配置文件中的数据库名称:: 创建数据库,如果不存在`websocket_chatroom`默认字符集`utf8`; 使用`websocket_c ...

  7. 基于django channel 实现websocket的聊天室

    websocket ​ 网易聊天室? ​ web微信? ​ 直播? 假如你工作以后,你的老板让你来开发一个内部的微信程序,你需要怎么办?我们先来分析一下里面的技术难点 消息的实时性? 实现群聊 现在有 ...

  8. 视频教程-基于Java的WebSocket的聊天室-Java

    基于Java的WebSocket的聊天室 多年 Java 企业级应用开发工作经验,曾参与中国人寿.华夏人寿.泰康人寿.信达财险等保险行业内部业务管理系统以及线上在线产品的开发:参与中国人民银行.清华大 ...

  9. Python用tornado的websocket开发聊天室

    Python用tornado的websocket开发聊天室 用tornado开发基于异步websocket聊天室-demo 目录结构 Python包 main.py app/views.py temp ...

最新文章

  1. pycuda write complex numbers — errors:class “cuComplex” has no member “i”
  2. 王石:我每天都强迫自己做的一件事
  3. document.getElementById 学习总结
  4. oracle添加表的索引,oracle批量添加指定表前缀的索引SQL语句
  5. .net framework摘抄与理解
  6. MongoDB 如何使用内存?为什么内存满了?
  7. 【原创】关于MATLAB中imagesc函数图像保存的问题
  8. linux 3.10中完成量的使用
  9. php 5.4 安装xcache,安装xcache为你的PHP加速
  10. 2019118_四个化学数据分析(1)
  11. JDBCUtils——DBCP
  12. Spring Cloud Alibaba Sentinel之热点参数限流篇
  13. CentOS7 下MariaDB安装与简单配置
  14. 有哪些免费批量删除PDF文档的页码的方法
  15. 解决IOS浏览器或者微信浏览器播放audio音效第二次播放不全
  16. 如何用手机远程控制电脑
  17. MPCS-314 1A 光电耦合器 用于IGBT/MOSFET隔离栅极驱动 完美代替ELS3150 亿光
  18. android面试题分析总结
  19. Fusion APP-添加检查软件更新功能
  20. mysql中如何统计数据_mysql中的数据统计方法

热门文章

  1. 【教程】openstack all-in-one 方式安装stein版本教程
  2. 大学python搜题软件_中国大学MOOC的APP(慕课)用Python玩转数据答案搜题公众号
  3. 百度地图 设置缩放等级
  4. Burpsuite安全测试测试指导
  5. Effective C++(编写new和delete时需固守常规)
  6. 好看留言板源码php,挑战最棒的留言本的源码(一)
  7. 风力机叶片气动设计 matlab 程序,基于Matlab的1.5MW风力机叶片设计和优化方法
  8. win 10计算机文件,教你win10电脑怎么打开ai文件
  9. 微信公众号管理欧宁泰php,EasySwoole搭建高效微信管理后台
  10. CAD怎么添加剖面符号?CAD剖面符号绘制教程