go get github.com/gorilla/websocket
beego中代码使用
以下代码是controller核心部分代码,router等代码则不展示。
package controllers
import (
"fmt"
"github.com/astaxie/beego"
"net/http"
"github.com/gorilla/websocket"
)
type MySocketController struct {
beego.Controller
}
// 定义数据结构{"表格id1": {客户端浏览器id: true}, "表格id2": {客户端浏览器id: true}}
var tableClinets = make(map[string]map[*websocket.Conn]bool)
func (c *MySocketController) Get() {
ws, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil)
if err != nil{
beego.Info(err)
}
defer ws.CloseHandler()
// 这里是我用户的结构体,你可以按自己需要定义
var msg models.RecvWs
for {
err := ws.ReadJSON(&msg)
if err != nil {
beego.Info("页面可能断开啦")
for k,v := range tableClinets{
if _,ok := v[ws];ok{
delete(v, ws)
if len(v) == 0{
delete(tableClinets,k)
}
fmt.Println(tableClinets)
}
}
break
}
// 获取表格ID,判断是否存在数据结构中,不存在插入。
tableId := msg.TableUuid
if sockets, ok := tableClinets[tableId]; ok{
if _, ok := sockets[ws]; !ok{
sockets[ws] = true
}
}else{
client_map := map[*websocket.Conn]bool{ws: true}
tableClinets[tableId] = client_map
}
// 将获取的消息按表格ID广播出去
clients := tableClinets[tableId]
go func(msg models.RecvWs){
// 开启协程去做一些操作,例如可以实时去修改库里的内容
}(msg)
// 将消息广播的同时要把自己的客户端除去,自己不能给自己广播。
for client := range clients{
if client != ws{
err = client.WriteJSON(msg)
if err != nil {
client.Close()
delete(clients, client)
if len(clients) == 0{
delete(tableClinets,msg.TableUuid)
}
}
}
}
}
}
前端代码
注意temp是用来存放后端第一次返回来的数据,在jexcel监测到表格有变化时一定要先去temp去看看有没有,没有则向后端发送。不然会造成后端向前端推数据时,前端表格发生变化,执行了onchange,又向后端发送,后端又广播出去,一个死循环。具体把控可根据业务来。
var temp = {}
var ws = new WebSocket('ws://ip地址:8080/ws');
ws.onopen = function(){
// 第一个建立连接时向后端发送一个数据,让后端保存好socket,和文档的uuid
var data = {
"file_id": file_id,
"first_status": "true"
}
req_data = JSON.stringify(data);
ws.send(req_data)
// 初始化表格
$("#mytable").jexcel({
data: table_size,
defaultColWidth: res.table_width,
tableOverflow: true,
onchange: change_data,
});
};
// 定义发送数据的函数, 表格ID和别的信息
var change_data = function(instance, cell, x, y, value){
var data = {
"file_id": file_id,
}
// 尝试从temp_data字典中获取该单元格的数据, 并判断数据的来源
if(temp_data.hasOwnProperty(cellName)){
if(temp_data[cellName]==value){
delete temp_data[cellName];
return
}
delete temp_data[cellName];
}
req_data = JSON.stringify(data);
ws.send(req_data)
}
// 用来接收后端广播的消息,并渲染到表格上
ws.onmessage = function (res) {
var received_msg = res.data;
var obj = JSON.parse(received_msg);
var cellName = obj["update_name"]
var value = obj["update_value"]
// 改变单元格的内容
$("#mytable").jexcel('setValue', cellName, value)
};
示例
以下为企业微信(腾讯定制-安信)小程序开发单个页面。