2023/12/10总结

学习

WebSocket

一共四种方法,传递数据是要通过JSON格式传递

前端

  • onopen

在连接时

  • onmessage

收到消息时 通常携带参数 event  ,event.data 是消息

2023/12/10总结_第1张图片

  • onerror

发生错误时

  • onclose

关闭连接时

2023/12/10总结_第2张图片

  • 发送消息

需要安装 vue-native-websocket

pnpm i vue-native-websocket

然后为了全局使用,我是放在了 pinia 状态管理工具里面,来实现

import {defineStore} from "pinia";
import {h, ref} from 'vue'
import {useUserStore} from "@/stores/userStore";
import {ElMessage, ElNotification} from "element-plus";
import {messageTitle} from "@/utils/MessageTitle";

export const useWsStore=defineStore("ws",()=>{

    let ws=null
    const userStore=useUserStore()

    const message=ref({})

    const wsInit=()=>{
        if (ws && ws.readyState === WebSocket.OPEN) {
            console.log('WebSocket 连接已经存在');
            return false
        }

        if(typeof(WebSocket) === "undefined"){
            alert("您的浏览器不支持socket")
            return false
        }

        const open1 = (msg) => {
            ElNotification({
                title: '消息',
                message: h('i', { style: 'color: teal' }, msg),
            })
        }

        ws=new WebSocket("ws://localhost:8081/api/websocket"+'/'+userStore.user.id)
        console.log("ws连接已经建立")

        ws.onmessage=(event)=>{
            console.log("收到了消息"+event.data)

            const {messageType,receiverId,t}={...JSON.parse(event.data)}

            if(receiverId!==userStore.user.id)
            {
                return
            }

            message.value=JSON.parse(event.data)

            open1(messageTitle[messageType])
        }

        ws.onerror=()=>{
            ElMessage.error("网络连接出错")
        }

        ws.onclose=()=>{
            ElMessage.error("连接已经关闭")
        }
    }

    const sendMessage=(type,receiverId,data)=>{
        if(ws&&ws.readyState===WebSocket.OPEN)
        {
            ws.send(JSON.stringify({messageType:type,receiverId,t:data}))
        }
        else
        {
            ElMessage.error("当前连接已经断开,请重试")
        }
    }

    return {
        ws,
        message,
        wsInit,
        sendMessage
    }
})

然后只需要在组件挂载的时候初始化,并且监听 watch message的变化去做出界面的改变就行。

后端

  • 依赖

            org.slf4j
            slf4j-log4j12
            2.0.7
        


        
            org.springframework.boot
            spring-boot-starter-websocket
        
  • 配置类
@Configuration
@EnableWebSocket
public class WebSocketConfig {

    /**
     * 	注入ServerEndpointExporter,
     * 	这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}
  • websocket类

2023/12/10总结_第3张图片

启动类需要加注解 @EnableWebSocket

  • onopen

2023/12/10总结_第4张图片

  • onmessage

2023/12/10总结_第5张图片

  • onerror

2023/12/10总结_第6张图片

  • onclose

2023/12/10总结_第7张图片

然后就是需要注意的一个地方,spring管理的都是单例(singleton),和 websocket (多对象)相冲突。 详细解释:项目启动时初始化,会初始化 websocket (非用户连接的),spring 同时会为其注入 service,该对象的 service 不是 null,被成功注入。但是,由于 spring 默认管理的是单例,所以只会注入一次 service。当新用户进入聊天时,系统又会创建一个新的 websocket 对象.

解决方法:

  • 启动类:
@EnableTransactionManagement
@ServletComponentScan
@SpringBootApplication
@EnableWebSocket
public class ElmApplication {

    public static void main(String[] args) {

        SpringApplication springApplication = new SpringApplication(ElmApplication.class);
        ConfigurableApplicationContext configurableApplicationContext = springApplication.run(args);

//        SpringApplication.run(ElmApplication.class, args);
        WebSocket.setApplicationContext(configurableApplicationContext);
    }

}
  • socket对象

2023/12/10总结_第8张图片

  • 使用

项目完成:

聊天

界面:

2023/12/10总结_第9张图片

2023/12/10总结_第10张图片

2023/12/10总结_第11张图片

评论:

2023/12/10总结_第12张图片

评论还有一部分没写完,是因为要在订单的处理上要实现消息推送,就还没写完。但是可以发布了,数据库能够写入数据。

你可能感兴趣的:(vue.js,前端,javascript)