node+vue3+websocket实现简易的聊天功能

后台接口代码

1、首先我们可以通过Express 应用程序生成器快速搭建一个后台框架。(这快可以参考官网

2、安装ws

npm install  express-ws

3、编写后台代码接口

简单逻辑说明:
1.创建连接
2.每个用户都有一个conn 那把conn存入到数组里方便以后广播所接受到的消息,去传达到其他用户
3.对用户数量做一个统计
4.接收到前端传来设置的用户名

代码如下:
在routes文件下新建一个ws.js文件
在这里插入图片描述

let express = require("express")
const expressWs = require("express-ws")
let router = express.Router()
expressWs(router)
let count = 0
//存放所有连接的用户
let connections = []
router.ws("/", (conn) => {
  //每个用户都有一个conn
  count++
  console.log(`游客进入聊天室,当前在线人数${count}`)
  sendMsg(conn, "count", count)
  //接收用户发来的数据
  conn.on("message", function (msg) {
    let obj = JSON.parse(msg)
    console.log(obj)
    if (obj.type === "name") {
      conn.userName = obj.author
      connections.push(conn)
      console.log(`用户的名字为${conn.userName},当前在线人数${count}`)
    } else if (obj.type === "submit") {
      broadcast("message", obj)
    }
  })
  //监听关闭状态
  conn.on("close", function () {
    count--
    // broadcast(JSON.stringify({ type: "count", data: count }))
    broadcast(
      JSON.stringify({
        type: "toast",
        data: `${conn.userName}离开了聊天室,当前在线人数${count}`
      })
    )
    console.log(
      `用户:${
        conn.userName ? conn.userName : "游客"
      }离开了聊天室,当前在线人数${count}`
    )
  })
})

function broadcast(type, data) {
  // 群发消息给所有用户
  connections.forEach((item) => {
    item.send(JSON.stringify({ type: type, data: data }))
  })
}
//单独发送给一个用户
function sendMsg(conn, type, data) {
  conn.send(JSON.stringify({ type: type, data: data }))
}
module.exports = router

4、注册路由

在app.js文件注册路由

var wsRouter = require('./routes/ws');
app.use('/wss', wsRouter);

5、bin/www 配置

由于 express-ws 在默认不添加server 参数情况下,使用的是app.listen 创建的httpserver,而express 脚手架将 app和server初始化分离了,所以需要再次配置express-ws

var expressWs = require('express-ws')(app, server);

前端代码

效果展示
前端效果
UI用的Ant Design of Vue Comment组件
类似一个实时评论回复的效果
代码展示:

<template>
    <a-list class="show-box" v-if="comments.length" :data-source="comments" item-layout="horizontal">
        <template #renderItem="{ item }">
            <a-list-item>
                <a-comment :author="item.author" :avatar="item.avatar" :content="item.content" :datetime="item.datetime" />
            </a-list-item>
        </template>
    </a-list>
    <a-comment>
        <template #avatar>
            <a-avatar :src="userInfo?.avatar" />
        </template>
        <template #content>
            <a-form-item>
                <a-textarea v-model:value="value" :rows="4" />
            </a-form-item>
            <a-form-item>
                <a-button html-type="submit" :loading="submitting" type="primary" @click="handleSubmit">
                    Add Comment
                </a-button>
            </a-form-item>
        </template>
    </a-comment>
</template>
<script lang="ts" setup>
import { ref, onUnmounted, onMounted } from 'vue';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
dayjs.extend(relativeTime);
type Comment = Record<string, string>;
const userInfo = JSON.parse(localStorage.getItem('userInfo') as string)
// 建立连接
const wsUrl = `ws://${location.host}/socket/wss`
const websock = new WebSocket(wsUrl);
// 建立连接后发送给后台存用户名
websock.onopen = (evt) => {
    console.log("Connection open ...");
    websock.send(JSON.stringify({
        type: 'name',
        author: userInfo?.nickName,
    }));
};
// 监听后台推送的信息(渲染评论)
websock.onmessage = (e) => {
    const res = JSON.parse(e?.data)
    console.log(res);
    if (res.type === 'message') {
        setTimeout(() => {
            submitting.value = false;
            comments.value = [
                ...comments.value,
                res.data,
            ];
            value.value = '';
        }, 1000);
    }
}
const comments = ref<Comment[]>([]);
const submitting = ref<boolean>(false);
const value = ref<string>('');
// 提交评论发送后台
const handleSubmit = () => {
    if (!value.value) {
        return;
    }
    submitting.value = true;
    const obj = {
        type: 'submit',
        author: userInfo?.nickName,
        avatar: userInfo?.avatar,
        content: value.value,
        datetime: dayjs().format('YYYY/MM/DD HH:mm:ss'),
    }
    websock.send(JSON.stringify(obj));
};
// 断开连接
onUnmounted(() => {
    websock.close();
});
</script>
<style lang="less" scoped>
.show-box {
    max-height: 520px;
    overflow: auto;
}
</style>

代理转发
vite.config.js

server:{
    proxy:{
       '/api':{
           target: "http://localhost:3000", //跨域地址
           changeOrigin: true, //支持跨域
           rewrite: (path) => path.replace(/^\/api/, "")//重写路径,替换/api
       },
       '/socket': {
        target: 'ws://localhost:3000',
        ws: true,
        rewrite: (path) => path.replace(/^\/socket/, "")
      },
    }
 }

源码地址

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这里是一个示例的Spring Boot + Vue.js + WebSocket的在线聊天应用程序的实现。首先,我们可以创建一个Spring Boot工程,然后添加WebSocket的依赖。 在pom.xml文件中添加以下依赖: ```xml <dependencies> <!-- ... --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies> ``` 接下来,我们可以编写一个WebSocket配置类,用于注册WebSocket端点和处理器: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new ChatWebSocketHandler(), "/chat"); } } ``` 这里我们注册了一个名为“chat”的WebSocket端点,并将其与一个处理器绑定。 接下来,我们可以编写一个WebSocket处理器类来处理来自客户端的消息: ```java public class ChatWebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessions.add(session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { for (WebSocketSession s : sessions) { if (s.isOpen()) { s.sendMessage(message); } } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessions.remove(session); } } ``` 这个处理器类中,我们定义了一个静态的WebSocketSession列表,用于存储所有连接到服务器的WebSocket会话。在`afterConnectionEstablished`方法中,我们将新的会话添加到列表中。在`handleTextMessage`方法中,我们遍历所有会话并将接收到的消息发送给它们。在`afterConnectionClosed`方法中,我们将关闭的会话从列表中删除。 最后,我们可以编写一个简单的HTML页面,在页面中使用Vue.js和WebSocket API来实现在线聊天功能: ```html <!DOCTYPE html> <html> <head> <title>Chat Room</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <div v-for="message in messages">{{ message }}</div> <input v-model="inputMessage" @keyup.enter="send"> </div> <script> var ws = new WebSocket("ws://" + window.location.host + "/chat"); var app = new Vue({ el: '#app', data: { messages: [], inputMessage: '' }, methods: { send: function () { ws.send(this.inputMessage); this.inputMessage = ''; } } }); ws.onmessage = function (event) { app.messages.push(event.data); }; </script> </body> </html> ``` 在这个HTML页面中,我们使用Vue.js来实现数据绑定和事件处理。我们还使用WebSocket API来连接到WebSocket服务器,并在收到消息时更新Vue.js的数据模型。在输入框中按下回车键时,我们将输入框中的内容发送到WebSocket服务器。 以上就是一个简单的Spring Boot + Vue.js + WebSocket的在线聊天应用程序的实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值