本项目是基于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); } } } } }
复制