WebSocket是什么?
WebSocket协议实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。
想用WebSocket干什么?
之前做过一款任务管理的产品,项目的看板页面,所有相关成员都可以修改,怎么保证修改的信息实时同步给其他成员?用WebSocket轻松搞定。
具体怎么做呢?
我们分前后两端来说明。先看后端核心代码。
首先,定义一个线程安全的Set,用来存放每个客户端对应的WebSocket对象。
private static CopyOnWriteArraySet<KbWebSocketServer> webSocketSet = new CopyOnWriteArraySet<KbWebSocketServer>();
WebSocket有四个核心处理方法,分别是open、close、message、error。其中open和close可以用来统计在线用户数,代码非常简单。这块不是我关注的,直接看一下代码:
/**
* 连接方法*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSocketSet.add(this);
try {
sendMessage("连接成功");
} catch (IOException e) {
log.error("websocket IO异常",e);
}
}
/**
* 关闭方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this);
log.info("关闭连接");
}
实时消息的传送是我要解决的核心问题。用户A页面修改了数据信息,后端接收到数据之后,需要将最新的数据分发给当前连接的所有用户。在这里,我消息体只包含数据id,之所以没有将详细信息全部当做消息体传送,第一是考虑到消息体简洁快捷传输,第二是客户端的处理也更加灵活,第三保留一定的扩展性(后期确实改造了)。看一下代码:
/**
* 收到客户端消息
* */
@OnMessage
public void onMessage(String message, Session session) {
for (KbWebSocketServer item : webSocketSet) {
try {
if(!session.getId().equals(item.session.getId())){
item.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
代码真的很简单,如果不考虑源码,只是使用的话,都没什么需要解释的。
接下来看看前端的处理。首先是初始化,这里有个需要注意的问题,最好做一个判断,因为有的浏览器不支持WebSocket,是的,你没有看错,是浏览器不支持。当然这个应该也有解决方案,不过我没有处理。。。
initScoket() {
if (typeof WebSocket === "undefined") {
this.$message("您的浏览器不支持socket,看板数据不支持实时变动");
} else {
this.socket = new WebSocket(this.path);
this.socket.onopen = this.open;
this.socket.onerror = this.error;
this.socket.onmessage = this.getMessage;
this.socket.onclose = this.close;
}
},
主要看一下接收服务端消息的代码。我前端使用的VUE,不过这没什么关系,都是javascript,目的只是接收到msg,至于后续的处理,可以根据自己的需求决定,如果你需要实时处理其他业务,可以在msg中增加类型,然后再接收到之后分别处理,这也是前面说的留一定的扩展。
getMessage(msg) {
let para = JSON.parse(msg.data);
if (this.$refs.routerView) {
this.$refs.routerView.getSocketMessage(para);
}
},
当然啦,也可以向服务端发送消息。将参数封装成json,由send方法发送。
webSocketSend(params) {
this.socketParams.orderId = params.orderId;
this.socketParams.projectId = params.projectId;
this.socketParams.messageType = params.messageType;
this.socket.send(JSON.stringify(this.socketParams));
},