首页 前端知识 基于websocket Redis的实时聊天系统

基于websocket Redis的实时聊天系统

2024-04-13 09:04:31 前端知识 前端哥 254 932 我要收藏

        本项目是基于websocket的实时聊天系统,由于在项目开发中需要使用到在线聊天功能,所以学了websocket来实现了这个功能。能够实时推送聊天记录,使用Redis保存聊天记录和聊天列表。用户上线后可以查看与别人的聊天记录和最近的聊天用户。在网上搜索了很久,都没有看到合适的项目,所以自己写了一套。

效果图

 

 消息 封装类 ChatMessage.java

/**
 * {@code @Description}: 聊天信息封装
 */
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Data
public class ChatMessage {
//    接收者用户名
    private String recipientUsername;
//    接收者头像地址
    private String recipienHeadUrl;
//    接收者网名
    private String recipienName;
//    发送者用户名
    private String senderUsername;
//    发送者头像地址
    private String senderName;
//    发送者网名
    private String senderHeadUrl;
//    消息
    private String message;
//    发送时间
    private String date;
}

聊天列表封装类  ChatList.java

/**
 * {@code @Description}: 描述
 */
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class ChatList {
    //    用户名
    private String username;
    //    头像地址
    private String recipienHeadUrl;
    //    网名
    private String screenName;

}

消息推送类 ChatWebSocketServer.java

@Component("chat")
@ServerEndpoint(value = "/chat/{recipientUsername}/{sender}")
public class ChatWebSocketServer {
     private static RedisTemplate redisTemplate;
     @Autowired
     @Qualifier("myredis")
     public void setRedisTemplate(RedisTemplate redisTemplate){
         this.redisTemplate = redisTemplate;
     }
    private final static Logger log = LoggerFactory.getLogger(ChatWebSocketServer.class);
    private Session session;

    private static ConcurrentHashMap<String, ChatWebSocketServer> websocketMap = new ConcurrentHashMap<>();
    private String recipientUsername;
    @OnOpen
    public void onOpen(Session session,@PathParam("recipientUsername") String recipientUsername,@PathParam("sender") String sender)
    {
        this.session = session;
        websocketMap.put(recipientUsername,this); //加入map中
        this.recipientUsername=recipientUsername;
        try {
            memor(recipientUsername,sender);
        } catch (Exception e) {

            log.error("websocket IO异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {

        if(websocketMap.get(this.recipientUsername)!=null){
            websocketMap.remove(this.recipientUsername);  //从map中删除

        }
    }
    
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
    }
    
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

//    自定义消息推送
    public  void sendMessage(ChatMessage chatMessage) {
        if(StringUtils.isNotBlank(chatMessage.getMessage())){
            ChatWebSocketServer webSocketServer = websocketMap.get(chatMessage.getRecipientUsername());
            if (webSocketServer != null) {
                try {
                    webSocketServer.sendMessage("chat:"+chatMessage.toString());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
//            将信息保存在Redis
            redisTemplate.opsForList().leftPush("chat:"+chatMessage.getRecipientUsername()+":"+chatMessage.getSenderUsername(),"chat:"+JSON.toJSONString(chatMessage));
//            redisTemplate.opsForList().leftPush("chat:"+chatMessage.getSenderUsername()+":"+chatMessage.getRecipientUsername(),"chat:"+JSON.toJSONString(chatMessage));

//            保存会话列表
            redisTemplate.opsForSet().add("chatList:"+chatMessage.getRecipientUsername(),JSON.toJSONString(new ChatList(chatMessage.getSenderUsername(),chatMessage.getSenderHeadUrl(),chatMessage.getSenderName())));
            redisTemplate.opsForSet().add("chatList:"+chatMessage.getSenderUsername(),JSON.toJSONString(new ChatList(chatMessage.getRecipientUsername(),chatMessage.getRecipienHeadUrl(),chatMessage.getRecipienName())));

//            回显消息
            ChatWebSocketServer webSocket = websocketMap.get(chatMessage.getSenderUsername());
            if (webSocket!=null) {
                try {
                    webSocket.sendMessage("chat:"+chatMessage.toString());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

        }

    }
//    推送缓存信息
    public void memor(String recipientUsername, String sender){
        List range = redisTemplate.opsForList().range("chat:"+recipientUsername+":"+sender, 0, -1);
        List range1 = redisTemplate.opsForList().range("chat:"+sender+":"+recipientUsername, 0, -1);
        range.addAll(range1);
        if (range!=null&&range.size()>0) {
            List<ChatMessage>chatMessageList = new ArrayList<>();
            Iterator iterator = range.iterator();
            while (iterator.hasNext()) {
                        Object next = iterator.next();
                        ChatMessage chatMessage = JSON.parseObject(String.valueOf(next).replace("chat:", ""),ChatMessage.class);
                        chatMessageList.add(chatMessage);
                    }


//                按时间排序
                chatMessageList.sort((ChatMessage c1,ChatMessage c2)->{
                    return c1.getDate().compareTo(c2.getDate());
                });
//                发送
                Iterator<ChatMessage> iterator1 = chatMessageList.iterator();
                while (iterator1.hasNext()) {
                    try {
                        ChatWebSocketServer webSocketServer = websocketMap.get(recipientUsername);
                        if (webSocketServer != null) {
                            ChatMessage next = iterator1.next();
                            webSocketServer.sendMessage("chat:"+String.valueOf(next));
                        }
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }

转载请注明出处或者链接地址:https://www.qianduange.cn//article/4838.html
标签
评论
发布的文章

JQuery中的load()、$

2024-05-10 08:05:15

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!