技术心得记录:基于webSocket的聊天室

简介: 技术心得记录:基于webSocket的聊天室

前言


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


websocket是什么?


至于websocket是什么、有什么用这样的问题一Google一大把,这里我就简要的说些websocket再本次实例中的作用吧。


由于在本次实例中需要实现的是一个聊天室,一个实时的聊天室。如下图:


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


后端


既然推出了websocket,作为现在主流的Java肯定也有相应的支持,所以在JavaEE7之后也对websocket做出了规范,所以本次的代码理论上是要运行在Java1.7+和Tomcat7.0+之上的。


看过我前面几篇文章的朋友应该都知道本次实例也是运行在之前的SSM之上的,所以这里就不再赘述了。


首先第一步需要加入websocket的依赖:


1 package com.css.tax.mobilebs.util;


2


3 import java.io.IOException;


4 import java.io.UnsupportedEncodingException;


5 import java.util.Date;


6 import java.util.HashMap;


7 import java.util.Iterator;


8 import java.util.Map;


9 import java.util.concurrent.CopyOnWriteArraySet;


10


11 import javax.websocket.OnClose;


12 import javax.websocket.OnError;


13 import javax.websocket.OnMessage;


14 import javax.websocket.OnOpen;


15 import javax.websocket.Session;


16 import javax.websocket.server.PathParam;


17 import javax.websocket.server.ServerEndpoint;


18


19 import org.g4studio.common.dao.Reader;


20 import org.g4studio.common.service.impl.BaseServiceImpl;


21 import org.g4studio.common.util.SpringBeanLoader;


22 import org.g4studio.common.web.BaseAction;


23 import org.g4studio.core.metatype.Dto;


24 import org.g4studio.core.metatype.impl.BaseDto;


25 import org.junit.Test;


26


27 import com.css.tax.mobilebs.Vo.CurrentUserVo;

//代码效果参考: http://www.jhylw.com.cn/130439823.html


28 import com.css.tax.mobilebs.serviceI.WebSocketService;


29 import com.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 extends BaseAction{


37 // 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。


38 private static int onlineCount = 0;


39 // concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识


40 private static CopyOnWriteArraySet

= new CopyOnWriteArraySet

41 private static CopyOnWriteArraySet

42 private WebSocketService zjzzWebSocketService = (WebSocketService)super.getService("zjzzWebSocketService");


43 // 与某个客户端的连接会话,需要通过它来给客户端发送数据


44 private Session session;


45 private Map webSocketMap = new HashMap();


46 private CurrentUserVo currentUserVo = new CurrentUserVo();


47


48 /


49 连接建立成功调用的方法


50


51 @param session


52 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据


53 /


54 @OnOpen


55 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 @OnClose


89 public void onClose() {


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 @param message


103 客户端发送过来的消息


104 @param session


105 可选的参数


106 /


107 @OnMessage


108 public void onMessage(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

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 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 = new BaseDto();


156 reDto.put("uuid", uuid);


157 reDto.put("ckbz", "Y");


158 reDto.put("xgr_dm", "111");


159 reDto.put("xgsj", SystemUtils.dateFormat(new Date()));


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 map = (Map) 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 = new BaseDto();


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(new Date()));


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(t

相关文章
|
2月前
|
网络协议 算法
WebSocket 技术详解
【2月更文挑战第12天】
117 1
|
3天前
|
NoSQL Redis Python
技术经验分享:Django实现websocket
技术经验分享:Django实现websocket
|
13天前
|
JavaScript 网络协议 前端开发
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
【Nodejs】WebSocket 全面解析+实战演练——(Nodejs实现简易聊天室)
47 0
|
2月前
|
网络协议 JavaScript 前端开发
WebSocket:实现客户端与服务器实时通信的技术
WebSocket:实现客户端与服务器实时通信的技术
|
20天前
|
监控 网络协议 JavaScript
WebSocket技术详解与应用指南
WebSocket是全双工TCP协议,解决HTTP的单向通信问题,允许服务器主动推送信息。本文档介绍了WebSocket的基本概念、工作原理(基于HTTP握手,通过帧进行数据通信)、应用场景(实时聊天、在线游戏、数据监控等)和实现方法(客户端使用JavaScript API,服务器端有多种编程语言库支持)。学习WebSocket能提升Web应用的实时性和交互性。
26 1
|
2月前
|
存储 JavaScript Java
基于 WebSocket 打造聊天室
基于 WebSocket 打造聊天室
|
2月前
|
存储 监控 BI
HIS系统是什么?一套前后端分离云HIS系统源码 接口技术RESTful API + WebSocket + WebService
医院管理信息系统(全称为Hospital Information System)即HIS系统。 常规模版包括门诊管理、住院管理、药房管理、药库管理、院长查询、电子处方、物资管理、媒体管理等,为医院管理提供更有力的保障。 HIS系统以财务信息、病人信息和物资信息为主线,通过对信息的收集、存储、传递、统计、分析、综合查询、报表输出和信息共享,及时为医院领导及各部门管理人员提供全面、准确的各种数据。 门诊医生工作站采用下拉式汉化菜单,界面友好,实用性强,设有与门诊挂号收费系统、医技科室信息系统、住院结算信息系统的软件接口。
58 1
|
2月前
|
前端开发 JavaScript Java
【十五】springboot整合WebSocket实现聊天室
【十五】springboot整合WebSocket实现聊天室
65 0
|
10月前
|
移动开发 前端开发 网络协议
WebSocket网页聊天室
WebSocket网页聊天室
121 0
|
10月前
|
JavaScript 前端开发 Java
SpringBoot+Vue搭建一个WebSocket的实时聊天室
SpringBoot+Vue搭建一个WebSocket的实时聊天室
171 0