最近需要做一個(gè)1v1對(duì)戰(zhàn)邀請(qǐng)咳焚,用到了socket茄靠,寫(xiě)一寫(xiě)使用方法
為什么使用websocket
因?yàn)樗梢韵蚍?wù)端發(fā)送信息
目前功能
- 能夠連接后臺(tái)驻龟,并維持連接
- 后臺(tái)能夠監(jiān)聽(tīng)每一位用戶载慈,給他/他們發(fā)送信息
- 前臺(tái)能夠接受信息。(這里擴(kuò)展了一下苫费,可以直接調(diào)用頁(yè)面method汤锨。)
ps:Vue寫(xiě)的前端,需要接收信息的頁(yè)面注冊(cè)到socket中百框,信息傳給前端時(shí)闲礼,招到頁(yè)面調(diào)用函數(shù)。
以下是代碼地址铐维,這里就不貼代碼了柬泽,更詳細(xì)的介紹會(huì)在readme中。
注意:需要放開(kāi)/bindingRecord/**
請(qǐng)求地址方椎,否則請(qǐng)求到不了后臺(tái)
覺(jué)得有用給個(gè)star一下吧
https://gitee.com/somliy/WebSocket
目錄介紹
├─websocket-java
│ ├─config // socket的配置文件
│ ├─entity // 通信時(shí)的實(shí)體類
│ ├─sender // 發(fā)送者
│ └─server // 服務(wù)端
└─websocket-js // 前端js部分 分為socketNotice.js 和 調(diào)用index.js
簡(jiǎn)單使用
前臺(tái):
url 不是以
http
開(kāi)始 是以ws://localhost:xxxx
開(kāi)始
import SocketNotice from './socketNotice'
let connection;
export default {
...省略
destroyed () {
// 釋放資源聂抢,以免頁(yè)面重復(fù)注冊(cè)
console.log('開(kāi)始銷毀')
this.$socket.unRegisterReceiver(this.$options.name)
},
methods: {
init() {
const url = 'ws://localhost:8888';
// 分別傳入 userId,url
connection = new SocketNotice(1, url);
// 建立連接
connection.connect();
// 注冊(cè)當(dāng)前頁(yè)面
// this.$options.name 可以獲取當(dāng)前文件名棠众,作為注冊(cè)組件的key存入
connection.registerReceiver(this.$options.name, this);
console.log('注冊(cè)組件', this.$options.name)
},
send() {
console.log('WEb發(fā)送信息 :Send Message Test! 給后臺(tái)');
connection.send(JSON.stringify(
{
cmd: 'TEST',
msg: '',
// key需要帶著琳疏,回調(diào)時(shí)使用
compName: this.$options.name,
data: 'Send Message Test!'
}
))
},
// 默認(rèn)調(diào)用此方法
onSocketMessage(data) {
console.log(`組件 ${this.$options.name} 收到信息為 :`, data)
}
}
}
后臺(tái):
將文件放入項(xiàng)目即可,(代碼中默認(rèn)給用戶id為1的發(fā)送消息)
需要放開(kāi)/bindingRecord/**
請(qǐng)求地址闸拿,否則請(qǐng)求到不了后臺(tái)
值得一提的是onMessage
方法
/**
* 接收到信息
*
* @param message
*/
@OnMessage
public void onMessage(String message, Session session) {
TestWebSocketService testWebSocketService = (TestWebSocketService) SpringContextUtil.getBean("testWebSocketService");
log.info("【收到】空盼,客戶端:{},的信息:{}新荤,連接總數(shù):{}", session.getId(), message, WebSocketSessionManager.getSize());
try {
NoticeData msg = objectMapper.readValue(message, NoticeData.class);
//有心跳回復(fù)一個(gè),其他情況暫不處理
if (NoticeData.Cmd.HEAR_BEAT.name().equals(msg.getCmd())) {
session.getBasicRemote().sendText(objectMapper.writeValueAsString(NoticeData.heartBeatReply()));
} else if (NoticeData.Cmd.TEST.name().equals(msg.getCmd())) {
// 處理業(yè)務(wù)邏輯
log.info("【接收消息】揽趾,類型:{},內(nèi)容:{}", msg.getCmd(), msg.getData().toString());
//-----------------------------------------------------------------------------------
// 這里收到消息后苛骨,立即給前臺(tái)發(fā)回信息篱瞎,只是測(cè)試使用,具體按照需要注入方法即可
NoticeData data = new NoticeData();
data.setCmd(NoticeData.Cmd.TEST.name());
data.setMsg("測(cè)試");
data.setCompName("Analysis");
data.setData("已收到信息痒芝,收到信息為" + msg.getData().toString());
testWebSocketService.test(data);
//-----------------------------------------------------------------------------------
}
} catch (Exception e) {
log.error("【處理消息異忱睿】,接收到ws=" + session.getId() + "消息處理時(shí)異常:" + message, e);
}
}
開(kāi)始使用
首先調(diào)用init
方法严衬,建立聯(lián)機(jī) 并 注冊(cè)頁(yè)面
然后調(diào)用send
方法
-
前端控制臺(tái)
-
后端控制臺(tái)
這樣到這里澄者,一個(gè)簡(jiǎn)單的示例完成了
但是還是有一個(gè)問(wèn)題,如何全局使用這個(gè)socket
把 socket 掛載到全局
每個(gè)前端都有一個(gè)獲取用戶信息的地方
// 首先判斷是否掛載
if (!Vue.prototype.$socket || !Vue.prototype.$socket.isConnected()) {
try {
const userId = store.getters.userInfo.userId
const url = process.env.VUE_APP_SCOCKET_BASE_URL
const connection = new SocketNotice(userId, url)
connection.connect()
// 掛載在Vue上请琳,以后可以使用 this.$socket 調(diào)用socket
Vue.prototype.$socket = connection
console.log('【W(wǎng)ebSocket】粱挡,初始化完成')
} catch (e) {
notification.error({
key: 'socketError',
message: '錯(cuò)誤',
description: JSON.stringify(e)
})
}
}