WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
POM
1 | <dependencies> |
YML
1 | server: |
@Configuration
重写modifyHandshake修改握手规则,用以向HttpSession存储WebSocket的Session。
1 |
|
@ServerEndpoint
服务端代码如下
configurator = WebConfig.class用以指定WebSocket配置类,该类需要继承javax.websocket.server.ServerEndpointConfig.Configurator。
value = "/test/oneToOne"用以指定客户端访问路径,该服务端的全路径访问地址格式为ws://+服务端IP+服务端口(server.port: 9119)+/test/oneToOne。
AtomicInteger onlineCount用以记录在线用户数量,AtomicInteger可保证并发请求时数量准确。
Map<String, Session> clients以Session.getId()为key,存储Session,用以对多个客户端发送消息。
onOpen()客户端连接成功
onClose()客户端关闭连接
onError()客户端连接出错
onMessage()接收到客户端消息,此处为接收String类型消息后,再行转换。下一节将介绍实现对应的接口后,自动转换。
1 |
|
前端代码
1 | if ("WebSocket" in window) { |
自动转换消息类型
建立常规实体类,实现
Serializable接口。建立两个转换类,分别实现
javax.websocket.Decoder.Text<Message>和javax.websocket.Encoder.Text<Message>接口并重写方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//Encoder
public String encode(Message message) throws EncodeException {
return JSON.toJSONString(message);
}
//Decoder
public Message decode(String message) throws DecodeException {
return JSON.parseObject(message, Message.class);
}
public boolean willDecode(String s) {
return true;
}服务端指定编码与解码消息对象类
1
服务端代码 重点:
sendMessage(Message message,Session toSession)方法中的接收参数必须与onMessage(Session session,Message message)的参数一致。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20private void sendMessage(Message message,Session toSession){
if (null == toSession) {
log.error("session is Null. id [{}]",message.getTo());
return;
}
try {
toSession.getBasicRemote().sendText(JSON.toJSONString(message));
log.info("server to [{}] send {} .",toSession.getId(), JSON.toJSONString(message));
} catch (IOException e) {
log.error("server to [{}] send {} failure . because : {}",toSession.getId(), JSON.toJSONString(message),e.getLocalizedMessage());
}
}
public void onMessage(Session session,Message message){
Session toSession = clients.get(message.getTo());
message.setFrom(session.getId());
sendMessage(message,toSession);
// return message;
}至止,
WebSocket传递普通文本已经粗略完成。