效果
在实现毕业设计时,中间有个功能需要实现不同聊天室不同用户之间的交流。
例如:
项目演示
SpringMVC整合websocket实现多聊天室聊天功能
原理讲解
创建多个不同的聊天室和实现对用户的分层管理。用户以医生的身份进入系统后,用户选择在线聊天,系统更改用户当前状态,并以其账号和姓名作为临时身份,并新建一个名称为医生账号的WebSocketsession,之后建立USER_SOCKETSESSION_MAP为房间里的每个人存储信息。将WebSocketsession存储到USER_SOCKETSESSION_MAP中,实现多人聊天室的功能。之后建立一个以自增长的数字为辨别符ROOM房间,将USER_SOCKETSESSION_MAP存储到ROOM中,用以区分每个聊天室。当用户以患者身份登录后,患者选者医生,并进入医生详情页,如果医生在线了话,则可以访问医生。用户选择医生后进入聊天室,后台会将要访问的医生账号放入WebSocketsession,系统在后台对比每个ROOM房间中USER_SOCKETSESSION_MAP里的WebSocketsession,当匹配完成后,将其WebSocketsession放进USER_SOCKETSESSION_MAP里对应的ROOM房间中。实现对房间分层多用户聊天操作。
实现步骤
1.区分聊天室
修改WebSocket的接收协议格式,使其可以接收以userid结尾的uri。其修改WebSocket协议的代码如下:
registry.addHandler(webSocketHandler,"/ws/{id}").addInterceptors(chatHandshakeInterceptor);
registry.addHandler(webSocketHandler,"/ws/sockjs/{id}").addInterceptors(chatHandshakeInterceptor).withSockJS();
在系统中要创建一个类型为HashMap的USER_SOCKETSESSION_MAP,并用userid作为标志区分每个房间里不同的用户,并将webSocketSession放入其中。之后创建类型为HashMap的ROOM用来存放不同的房间信息key作为每个房间的标志。创建USER_SOCKETSESSION_MAP和ROOM的代码如下:
final Map<String, WebSocketSession> USER_SOCKETSESSION_MAP;
final Map<Integer, Map<String, WebSocketSession>> ROOM;
static {
USER_SOCKETSESSION_MAP = new HashMap<String,WebSocketSession>();
ROOM=new HashMap<Integer, Map<String, WebSocketSession>>();
}
当患者选择要询问的主治医生后,系统将对应的医生账号写入WebSocketsession中去,当后台获取websocketsession后首先判断此时的房间ROOM是否为空,若为空房间则进行初始化操作,将websocketsession和登录用户id放入USER_SOCKETSESSION_MAP中,在初始化key为0,后将key和USER_SOCKETSESSION_MAP放入ROOM中。初始化代码如下:
if(ROOM==null || ROOM.isEmpty()){
Map<String, WebSocketSession> user_map= new HashMap<String, WebSocketSession>();
user_map.put(loginUser.getId(), webSocketSession);
ROOM.put(0, user_map);}
如果房间不为空则进行遍历查找,首先将ROOM分层一个一个的USER_SOCKETSESSION_MAP临时设为entry1,后将每个USER_SOCKETSESSION_MAP分层一个一个的WebSocketsession临时设为entry2。之后将得到的Websocketsession与每一个entry2中的uri对比,如果uri一样,则把当前的用户id和uri一起放入websocketsession中,将websocketsession放入对应ROOM中的USER_SOCKETSESSION_MAP中去,并设置flag值跳过后面的创建房间。最后跳出循环。寻找房间代码如下:
boolean flag=true;
here:
for(Map.Entry<Integer,Map<String,WebSocketSession>>entry1:ROOM.entrySet()){
for(Map.Entry<String,WebSocketSession>entry2:entry1.getValue().entrySet()){
if(entry2.getValue().getUri().equals(webSocketSession.getUri())){
key=entry1.getKey();
(ROOM.get(key)).put(loginUser.getId(), webSocketSession);
flag=false;
break here;
}
}
}
如果房间不为空且找不到房间时,将websocketsession和登录用户id放入USER_SOCKETSESSION_MAP中,提取当前ROOM房间的所有值,并进行排序,取得最大值,将key设置为最大值加一,后创建新的ROOM房间并将取到的key值和USER_SOCKETSESSION_MAP放入ROOM中去。不为空并创建新房间代码如下:
if(flag){
//无房间自增长添加房间
Set<Integer> set = ROOM.keySet();
Object[] obj = set.toArray();
Arrays.sort(obj);
key=obj.length;
Map<String, WebSocketSession> user_map= new HashMap<String, WebSocketSession>();
user_map.put(loginUser.getId(), webSocketSession);
ROOM.put(obj.length, user_map);
}
通过两个HashMap类型的变量完成对不同房间的创建和对不同用户的区分,实现不同房间的多用户聊天室。
2.发送消息
如果客户端有消息进来,需要先判断客户端的这条信息是从哪个聊天室发来的:
@Override
/**
* 客户端发送服务器的消息时的处理函数,在这里收到消息之后可以分发消息
*/
//处理消息:当一个新的WebSocket到达的时候,会被调用(在客户端通过Websocket API发送的消息会经过这里,然后进行相应的处理)
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> message) throws Exception {
// 判断哪个房间
here:
for(Map.Entry<Integer, Map<String, WebSocketSession>> entry1 : ROOM.entrySet()){
for(Map.Entry<String, WebSocketSession> entry2 : entry1.