博主
258
258
258
258
专辑

第二节 SpringBoot+Vue实现聊天室

亮子 2022-12-27 08:10:11 6344 0 0 0

1、创建websocket服务器

1)、引入依赖

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

也可以在创建项目的时候选择websocket:

图片alt

2)、添加配置类

package com.shenmazg6.chatroom.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @author 军哥
 * @version 1.0
 * @description: WebSocketConfig
 * @date 2022/12/27 14:29
 */

@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

3)服务端代码

package com.shenmazg6.chatroom.chat;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 军哥
 * @version 1.0
 * @description: UserWebSocket
 * @date 2022/12/27 14:33
 */

@Component
@Slf4j
@ServerEndpoint(value = "/chatRoom/{userId}")
public class UserWebSocket {

    // 当前对象的session
    private Session _session;

    // 当前用户ID
    private Integer userId;

    // 所有用户的列表
    private static Map<String, Session> userSessions = new ConcurrentHashMap<>();

    /**
     * 当连接建立成功时被调用
     * @param session
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId")Integer userId) {
        userSessions.put(session.getId(), session);
        this._session = session;
        this.userId = userId;
        log.info("onOpen,在线人数为:"+ userSessions.size());

        // 发送通知
        sendAllMessage("有新的小朋友【进来】了");

    }

    /**
     * 当连接端口时被调用
     */
    @OnClose
    public void onClose(Session session, @PathParam("userId")Integer userId) {
        userSessions.remove(session.getId());
        this._session = null;
        this.userId = null;

        log.info("onClose,在线人数为:"+ userSessions.size());


        // 发送通知
        sendAllMessage("有小朋友【离开】了");

    }

    /**
     * 当有消息到达时被调用
     * @param message
     * @param session
     */

    @OnMessage
    public void onMessage(String message, Session session, @PathParam("userId")Integer userId) {
        log.info("onMessage::"+ message);

        // 发送消息
        sendAllMessage(message);
    }

    @OnError
    public void onError(Session session, Throwable error, @PathParam("userId")Integer userId) {
        userSessions.remove(session.getId());
        this._session = null;
        this.userId = null;
        log.info("onError,在线人数为:"+ userSessions.size());


        // 发送通知
        sendAllMessage("有小朋友网络问题【离开】了");
    }

    /**
     * 主动发送消息
     * @param session
     * @param message
     * @throws IOException
     */
    public void sendMessage(Session session, String message) throws IOException {
        session.getBasicRemote().sendText(message);
    }

    public void sendAllMessage(String message) {
        userSessions.keySet().forEach(item -> {
            Session session = userSessions.get(item);

            try {
                session.getBasicRemote().sendText(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
            ;
        });
    }
}

4)、Vue代码

<template>
    <div>
        <div><h3>聊天室</h3></div>
        <div>
            <div>
                <el-input
                  type="textarea"
                  :autosize="{ minRows: 10, maxRows: 20}"
                  placeholder="聊天内容"
                  v-model="chatMessage">
                </el-input>
            </div>
            <div style="margin-top: 20px;">
                <el-form :inline="true" :model="formInline" class="demo-form-inline">
                  <el-form-item label="消息">
                    <el-input v-model="formInline.message" style="width: 600px;" placeholder="请输入消息"></el-input>
                  </el-form-item>
                  <el-form-item>
                    <el-button type="primary" @click="onSendMessage">发送消息</el-button>
                    <el-button type="primary" @click="onOpen">连接服务器</el-button>
                    <el-button type="primary" @click="onClose">断开连接</el-button>
                  </el-form-item>
                </el-form>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'ChatRoomPage',
        data() {
            return {
                chatMessage: '',
                formInline: {
                    message: '',
                },
                websocket: null,
                user: null,
                userId: 0,
            }
        },
        mounted() {
            let u = window.sessionStorage.getItem('user');
            if(u == null) {
                this.$router.push('/login');
                return;
            }
            this.user = JSON.parse(u);
            this.userId = this.user.userId;
        },
        methods: {
            // 发送消息
            onSendMessage() {
                let msg = this.formInline.message;
                this.websocket.send(this.user.userName+':'+msg);
                this.formInline.message = '';
            },
            // 连接服务器
            onOpen() {
                let url = "ws://localhost:8170/chatRoom/"+this.userId;
                
                // 打开一个websocket
                this.websocket = new WebSocket(url);
                
                // 建立连接
                this.websocket.onopen = this.open;
                
                // 客户端接收服务端返回的数据
                this.websocket.onmessage = this.getMessage;
                // 发生错误时
                this.websocket.onerror = this.error;
                // 关闭连接
                this.websocket.onclose = this.close;
            },
            // 断开服务器
            onClose() {
                this.websocket.close()
            },
            
            // 以下为websocket回调函数
            open() {
                console.log("socket连接成功")
                // 发送消息
                this.doSendMessage('大家好,我来了');
            },
            error() {
                console.log("连接错误")
            },
            getMessage(msg) {
                console.log('getMessage', msg.data)
                this.chatMessage = this.chatMessage + '\n';
                this.chatMessage = this.chatMessage + msg.data;
                console.log('getMessage2', this.chatMessage);
            },
            close() {
                console.log("socket已经关闭")
            },
            doSendMessage(msg) {
                this.websocket.send(this.user.userName+':'+msg);
            }
        }
    }
</script>

<style>
</style>

5)、演示效果

图片alt