2023/12/10总结

2023-12-13 03:33:29

学习

WebSocket

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

前端

  • onopen

在连接时

  • onmessage

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

  • onerror

发生错误时

  • onclose

关闭连接时

  • 发送消息

需要安装 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的变化去做出界面的改变就行。

后端

  • 依赖
<dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>2.0.7</version>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
  • 配置类
@Configuration
@EnableWebSocket
public class WebSocketConfig {

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

启动类需要加注解?@EnableWebSocket

  • onopen

  • onmessage

  • onerror

  • onclose

然后就是需要注意的一个地方,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对象

  • 使用

项目完成:

聊天

界面:

评论:

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

文章来源:https://blog.csdn.net/lxh0113/article/details/134917162
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。