current position:Home>Springboot + Vue to realize online chat (general version)

Springboot + Vue to realize online chat (general version)

2022-04-29 20:46:31Programmer Qingge

Just a few simple steps , You can realize online chat room !

Integration steps :

Back end Springboot

Springboot add to Pom rely on :

<!-- websocket -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

Remember to refresh after adding Maven, Lead the bag in .

stay common Catalog add Websocket To configure :

New this WebSocketConfig.java

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
    
    /** *  Into a ServerEndpointExporter, The Bean Will automatically register to use @ServerEndpoint Annotated with websocket endpoint */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
    
        return new ServerEndpointExporter();
    }
}

newly build component Folder
WebSocketServer.java

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/** * @author websocket service  */
@ServerEndpoint(value = "/imserver/{username}")
@Component
public class WebSocketServer {
    
    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    /** *  Record the current number of online connections  */
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    /** *  Connection establishment method called successfully  */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
    
        sessionMap.put(username, session);
        log.info(" New users have joined ,username={},  The current online population is :{}", username, sessionMap.size());
        JSONObject result = new JSONObject();
        JSONArray array = new JSONArray();
        result.set("users", array);
        for (Object key : sessionMap.keySet()) {
    
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("username", key);
            // {"username", "zhang", "username": "admin"}
            array.add(jsonObject);
        }
// {"users": [{"username": "zhang"},{ "username": "admin"}]}
        sendAllMessage(JSONUtil.toJsonStr(result));  //  Send messages to all clients in the background 
    }
    /** *  Connection closes the called method  */
    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
    
        sessionMap.remove(username);
        log.info(" There is a connection closed , remove username={} Users of session,  The current online population is :{}", username, sessionMap.size());
    }
    /** *  Method called upon receipt of a client message  *  The background receives the message sent by the client  * onMessage  It's a relay station for messages  *  Accept   Browser side  socket.send  Sent by  json data  * @param message  The message sent by the client  */
    @OnMessage
    public void onMessage(String message, Session session, @PathParam("username") String username) {
    
        log.info(" The server receives the user username={} The news of :{}", username, message);
        JSONObject obj = JSONUtil.parseObj(message);
        String toUsername = obj.getStr("to"); // to Indicates to which user , such as  admin
        String text = obj.getStr("text"); //  Text of the message sent  hello
        // {"to": "admin", "text": " Chat text "}
        Session toSession = sessionMap.get(toUsername); //  according to  to User name to get  session, Re pass session Send message text 
        if (toSession != null) {
    
            //  Server side   Assemble the message again , The assembled message contains the sender and the text content sent 
            // {"from": "zhang", "text": "hello"}
            JSONObject jsonObject = new JSONObject();
            jsonObject.set("from", username);  // from  yes  zhang
            jsonObject.set("text", text);  // text  Same as above text
            this.sendMessage(jsonObject.toString(), toSession);
            log.info(" Send to user username={}, news :{}", toUsername, jsonObject.toString());
        } else {
    
            log.info(" fail in send , User not found username={} Of session", toUsername);
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
    
        log.error(" An error occurred ");
        error.printStackTrace();
    }
    /** *  The server sends a message to the client  */
    private void sendMessage(String message, Session toSession) {
    
        try {
    
            log.info(" Server to client [{}] Send a message {}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
    
            log.error(" The server failed to send a message to the client ", e);
        }
    }
    /** *  The server sends messages to all clients  */
    private void sendAllMessage(String message) {
    
        try {
    
            for (Session session : sessionMap.values()) {
    
                log.info(" Server to client [{}] Send a message {}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
    
            log.error(" The server failed to send a message to the client ", e);
        }
    }
}

thus , The back-end code is integrated , After integration , Remember to restart your Springboot project

front end Vue

hold Im.vue Add to your Vue Inside the directory , direct copy Just go

<template>
  <div style="padding: 10px; margin-bottom: 50px">
    <el-row>
      <el-col :span="4">
        <el-card style="width: 300px; height: 300px; color: #333">
         <div style="padding-bottom: 10px; border-bottom: 1px solid #ccc"> Online users <span style="font-size: 12px">( Click the chat bubble to start chatting )</span></div>
          <div style="padding: 10px 0" v-for="user in users" :key="user.username">
            <span>{
   { user.username }}</span>
            <i class="el-icon-chat-dot-round" style="margin-left: 10px; font-size: 16px; cursor: pointer" @click="chatUser = user.username"></i>
            <span style="font-size: 12px;color: limegreen; margin-left: 5px" v-if="user.username === chatUser">chatting...</span>
          </div>
        </el-card>
      </el-col>
      <el-col :span="20">
        <div style="width: 800px; margin: 0 auto; background-color: white; border-radius: 5px; box-shadow: 0 0 10px #ccc">
          <div style="text-align: center; line-height: 50px;">
            Web The chat room ({
   { chatUser }})
          </div>
          <div style="height: 350px; overflow:auto; border-top: 1px solid #ccc" v-html="content"></div>
          <div style="height: 200px">
            <textarea v-model="text" style="height: 160px; width: 100%; padding: 20px; border: none; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; outline: none"></textarea>
            <div style="text-align: right; padding-right: 10px">
              <el-button type="primary" size="mini" @click="send"> send out </el-button>
            </div>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>
<script> import request from "@/utils/request"; let socket; export default {
       name: "Im", data() {
       return {
       circleUrl: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', user: {
      }, isCollapse: false, users: [], chatUser: '', text: "", messages: [], content: '' } }, created() {
       this.init() }, methods: {
       send() {
       if (!this.chatUser) {
       this.$message({
      type: 'warning', message: " Please choose a chat object "}) return; } if (!this.text) {
       this.$message({
      type: 'warning', message: " Please enter the content "}) } else {
       if (typeof (WebSocket) == "undefined") {
       console.log(" Your browser does not support it WebSocket"); } else {
       console.log(" Your browser supports WebSocket"); //  Assemble messages to be sent  json // {"from": "zhang", "to": "admin", "text": " Chat text "} let message = {
      from: this.user.username, to: this.chatUser, text: this.text} socket.send(JSON.stringify(message)); //  Will be assembled json Send it to the server , Forward by the server  this.messages.push({
      user: this.user.username, text: this.text}) //  Build message content , My message  this.createContent(null, this.user.username, this.text) this.text = ''; } } }, createContent(remoteUser, nowUser, text) {
       //  This method is used to put  json The chat message data is converted into  html Of . let html //  Current user message  if (nowUser) {
       // nowUser  Indicates whether to display chat messages sent by the current user , Green bubble  html = "<div class=\"el-row\" style=\"padding: 5px 0\">\n" + " <div class=\"el-col el-col-22\" style=\"text-align: right; padding-right: 10px\">\n" + " <div class=\"tip left\">" + text + "</div>\n" + " </div>\n" + " <div class=\"el-col el-col-2\">\n" + " <span class=\"el-avatar el-avatar--circle\" style=\"height: 40px; width: 40px; line-height: 40px;\">\n" + " <img src=\"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png\" style=\"object-fit: cover;\">\n" + " </span>\n" + " </div>\n" + "</div>"; } else if (remoteUser) {
       // remoteUser Represents a remote user chat message , Blue bubbles  html = "<div class=\"el-row\" style=\"padding: 5px 0\">\n" + " <div class=\"el-col el-col-2\" style=\"text-align: right\">\n" + " <span class=\"el-avatar el-avatar--circle\" style=\"height: 40px; width: 40px; line-height: 40px;\">\n" + " <img src=\"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png\" style=\"object-fit: cover;\">\n" + " </span>\n" + " </div>\n" + " <div class=\"el-col el-col-22\" style=\"text-align: left; padding-left: 10px\">\n" + " <div class=\"tip right\">" + text + "</div>\n" + " </div>\n" + "</div>"; } console.log(html) this.content += html; }, init() {
       this.user = sessionStorage.getItem("user") ? JSON.parse(sessionStorage.getItem("user")) : {
      } let username = this.user.username; let _this = this; if (typeof (WebSocket) == "undefined") {
       console.log(" Your browser does not support it WebSocket"); } else {
       console.log(" Your browser supports WebSocket"); let socketUrl = "ws://localhost:9090/imserver/" + username; if (socket != null) {
       socket.close(); socket = null; } //  To start a websocket service  socket = new WebSocket(socketUrl); // Open event  socket.onopen = function () {
       console.log("websocket Already opened "); }; //  The browser receives messages , Get the text message sent from the server  socket.onmessage = function (msg) {
       console.log(" Receive the data ====" + msg.data) let data = JSON.parse(msg.data) //  Yes, I received json Data analysis ,  Something like that : {"users": [{"username": "zhang"},{ "username": "admin"}]} if (data.users) {
       //  Get online personnel information  _this.users = data.users.filter(user => user.username !== username) //  Get all the user information of the current connection , And exclude yourself , I won't appear on my chat list  } else {
       //  If it is sent from the server json data   It doesn't contain  users  This key, So what's sent is the chat text json data  // // {"from": "zhang", "text": "hello"} if (data.from === _this.chatUser) {
       _this.messages.push(data) //  Build message content  _this.createContent(data.from, null, data.text) } } }; // Closing event  socket.onclose = function () {
       console.log("websocket closed "); }; // An error event occurred  socket.onerror = function () {
       console.log("websocket Something went wrong "); } } } } } </script>
<style> .tip {
       color: white; text-align: center; border-radius: 10px; font-family: sans-serif; padding: 10px; width:auto; display:inline-block !important; display:inline; } .right {
       background-color: deepskyblue; } .left {
       background-color: forestgreen; } </style>

Add a route :

{
    
  path: 'im',
  name: 'Im',
  component: () => import("@/views/Im"),
},

Or use sql:

INSERT INTO `online-chat`.`sys_menu`(`id`, `name`, `path`, `icon`, `description`, `pid`, `page_path`, `sort_num`) VALUES (11, ' The chat room ', '/im', 'el-icon-chat-dot-square', NULL, NULL, 'Im', 999);

Configuration menu ( Optional , Or you can assign the menu directly , It depends on the framework you use ):

<el-menu-item index="/im"> <i class="el-icon-chat-dot-round"></i> The chat room </el-menu-item>

Okay , front end Vue The code ends here .

start-up Vue, Then test it :

Be careful , You need to turn on 2 A window or 2 A browser to test !

Then click the chat bubble , To receive and send messages .

Code integration considerations

front end Vue Get the user is using sessionStorage Of , If you use localStorage Access user information , Then you have to open 2 Only one browser can work properly , Bear in mind !

copyright notice
author[Programmer Qingge],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2022/04/202204292046265621.html

Random recommended