Technical points
- websocket Technology
When it comes to chat rooms, the preferred technology is WebSocket, which is a single TCP Connect to full duplex Communication protocol, which is more suitable for business requirements than long connection and short connection
Personal summary: long and short connections and polling are passive on the server side, only the client can initiate the request first, and the passive type of http protocol is proposed; and the websocket server side can send multiple messages to the client
Design sketch
Chat message format
{ "toid":124, "message":"Hello?" }
Interactive Chat
sender
Recipient
Chat with robots
When Toid is 0, send to robot
Here we use the native websocket built directly on the spring boot. In fact, the real high concurrent and high traffic business scenario is definitely the first choice to use the netty framework.
@ServerEndpoint("/chat/{userId}") @Component public class WebChatServer { static Logger log= LoggerFactory.getLogger(WebChatServer.class); private static int onlineCount = 0; private static ConcurrentHashMap<Integer,WebChatServer> webSocketMap = new ConcurrentHashMap<>(); private Session session; private int userId= 0; static ChatRobot chatRobot; public WebChatServer(){ } @Autowired public WebChatServer(ChatRobot chatRobot){ this.chatRobot = chatRobot; } /** * Method successfully called for connection establishment*/ @OnOpen public void onOpen(Session session,@PathParam("userId") int userId) { this.session = session; webSocketMap.put(userId,this); //Join set addOnlineCount(); //Online data plus 1 log.info("New users start listening:"+userId+",The current number of people online is" + getOnlineCount()); this.userId=userId; try { sendMessage("Successful connection"); } catch (IOException e) { log.error("websocket IO abnormal"); } } /** * Method of connection close call */ @OnClose public void onClose() { webSocketMap.remove(this); //Remove from set subOnlineCount(); //Online number minus 1 log.info("There is a connection closed! The current number of people online is" + getOnlineCount()); } /** * Method of calling after receiving client message * * @param message Messages sent by clients*/ @OnMessage public void onMessage(String message, Session session) throws IOException { log.info("Received from user"+userId+"Information:"+message); try{ //Parse message JSONObject jsonObject = JSONObject.parseObject(message); int toid = (int)jsonObject.get("toid"); if (toid == 0){ WebChatServer webSocketServer = webSocketMap.get(toid); String messageContent = jsonObject.get("message").toString(); String chatContent = chatRobot.getChatContent(messageContent); sendMessage(chatContent); log.info("Reply message to user successfully"+userId+":"+chatContent); }else{ WebChatServer webSocketServer = webSocketMap.get(toid); if (webSocketServer != null){ String messageContent = jsonObject.get("message").toString(); webSocketServer.sendMessage(messageContent); log.info("Successfully sent message to user"+toid+":"+messageContent); } } }catch (Exception e){ System.out.println(e.toString()); sendMessage("The format of sending information is wrong. Please check and resend"); } } /** * * @param session * @param error */ @OnError public void onError(Session session, Throwable error) { log.error("Error occurred"); error.printStackTrace(); } /** * Implement server active push */ public void sendMessage(String message) throws IOException { this.session.getBasicRemote().sendText(message); } /** * Group custom message * */ public static void sendInfo(String message,@PathParam("userId") String userId) throws IOException { log.info("Push message to user"+userId+",Push content:"+message); } public static synchronized int getOnlineCount() { return onlineCount; } public static synchronized void addOnlineCount() { WebChatServer.onlineCount++; } public static synchronized void subOnlineCount() { WebChatServer.onlineCount--; } }
Source code: https://github.com/ChenHaoHu/tools