学习
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对象
- 使用
项目完成:
聊天
界面:
评论:
评论还有一部分没写完,是因为要在订单的处理上要实现消息推送,就还没写完。但是可以发布了,数据库能够写入数据。