package com.cloudpan.common.websocket;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cloudpan.common.RedisCache;
import com.cloudpan.entity.pojo.SysUserMessage;
import com.cloudpan.service.SysUserMessageService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@ServerEndpoint("/im/{userId}")
@Component
@Slf4j
@Data
public class WebSocketIMServer {
private static SysUserMessageService messageService;
//用来存储在线用户的信息
private static RedisCache redisCache;
private static Integer onlineCount = 0;
private static Map<String, Session> clients = new ConcurrentHashMap();
private Session session;
private String userId;
@Autowired
public void setSysUserMessageService(RedisCache redisCache){
WebSocketIMServer.redisCache = redisCache;
}
@Autowired
public void setRedisCache(SysUserMessageService messageService){
WebSocketIMServer.messageService = messageService;
}
@OnOpen
public void onOpen(@PathParam("userId") String userId, Session session) {
this.userId = userId;
this.session = session;
WebSocketIMServer.onlineCount++;
clients.put(userId, session);
//用户上线 判断有无 离线消息 有 发送离线消息
OffMsgSend(userId);
log.info("【websocket消息】连接成功, 总数:{},{}", clients.size(),clients);
//在redis中存储在线用户的key
Set<String> onlines = clients.keySet();
redisCache.setCacheSet("onlines",onlines);
log.info("当前在线的用户为:{}",onlines);
}
//用户每次连接,判断是否存在离线消息,从数据库获取
public void OffMsgSend(String key){
LambdaQueryWrapper<SysUserMessage> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysUserMessage::getToId,key)
.eq(SysUserMessage::getOffMsg,"1");
List<SysUserMessage> list = messageService.list(queryWrapper);
if (CollectionUtil.isNotEmpty(list)){
// 不为空 则 发送离线消息
for (SysUserMessage sysUserMessage : list) {
JSONObject object = JSON.parseObject(sysUserMessage.getTextMessage());
String fromId = object.getString("fromId");
String toId = object.getString("toId");
String textMessage = object.getString("textMessage");
sendUser(textMessage,toId);
}
list.forEach(ele -> {
ele.setOffMsg("0");
});
//更新为不是离线消息
messageService.updateBatchById(list);
}
}
@OnClose
public void onClose() {
Session session = clients.get(userId);
if (!ObjectUtils.isEmpty(session)){
clients.remove(userId);
WebSocketIMServer.onlineCount--;
//更新redis中的在线人数信息
redisCache.deleteObject("onlines");
Set<String> newOnelines= clients.keySet();
redisCache.setCacheSet("onlines",newOnelines);
log.info("【websocket消息】连接断开, 总数:{}", clients.size());
}
}
@OnMessage
public void onMessage(String message) {
log.info("【Websocket消息】收到客户端发来的消息:{}", message);
//将前端传来的数据进行转型
JSONObject object = JSON.parseObject(message);
//获取所有数据
String fromId = object.getString("fromId");
String toId = object.getString("toId");
//String textMessage = object.getString("textMessage");
Session toUser = clients.get(toId);
SysUserMessage sysUserMessage = new SysUserMessage();
sysUserMessage.setFromId(fromId);
sysUserMessage.setToId(toId);
sysUserMessage.setTextMessage(message);
if (toUser != null){
sendUser(message,toId);
try {
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
messageService.save(sysUserMessage);
}else {
//不在线情况 需要给发送消息者发送一份
try {
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
sysUserMessage.setOffMsg("1");
//离线消息
messageService.save(sysUserMessage);
}
}
@OnError
public void onError(Session session, Throwable throwable) {
throwable.printStackTrace();
log.error("WebSocket发生错误:" + throwable.getMessage());
}
//群发
public void sendAllUser(String message) {
// 向所有连接websocket的客户端发送消息
for (Session item : clients.values()) {
item.getAsyncRemote().sendText(message);
}
log.info("【发送消息】:", userId + "向" + clients.size() + "人发送消息:" + message);
}
//私发
public void sendUser(String message,String toUserId) {
//获取待发送的用户
Session user = clients.get(toUserId);
try {
user.getBasicRemote().sendText(message);
log.info(userId + "消息发送拉,{}",message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Websocket实现发送在线-离线消息
最新推荐文章于 2024-04-20 21:10:42 发布