WebSocket让客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。
浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
本文使用WebSocket实现简单的客户端与服务端建立长连接并互相发送文本消息。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
TextWebSocketHandler: 文本内容
BinaryWebSocketHandler:二进制内容
创建CustomizeWebSocketHandler类继承TextWebSocketHandler, 重写了父类AbstractWebSocketHandler的四个方法
@Component
public class CustomizeWebSocketHandler extends TextWebSocketHandler {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public void afterConnectionEstablished(WebSocketSession session) {
log.info("与客户端建立连接...");
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
session.close(CloseStatus.SERVER_ERROR);
log.error("连接异常", exception);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
super.afterConnectionClosed(session, status);
log.info("与客户端断开连接...");
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
// 获取客户端发送的消息
String msg = message.getPayload();
log.info("客户端发送消息:{}", msg);
// 发送消息给客户端
session.sendMessage(new TextMessage(msg));
// 关闭连接
// session.close(CloseStatus.NORMAL);
}
}
WebSocketSession: 代表每个客户端会话,提供了许多实用方法
创建
WebSocketServerConfigure配置类
,将自定义的CustomizeWebSocketHandler
注册到Spring Boot容器并设置拦截路径/webSocket
,凡是该路径请求的连接将自动连接到WebSocket服务端。
@Configuration
@EnableWebSocket//开启WebSocket相关功能
public class WebSocketServerConfigure implements WebSocketConfigurer {
@Autowired
private CustomizeWebSocketHandler customizeWebSocketHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册自定义customizeWebSocketHandler
registry.addHandler(customizeWebSocketHandler, "/webSocket").withSockJS();
}
}
SockJS 是一个浏览器 JavaScript 库,它提供了一个类似 WebSocket 的对象
SockJS 提供了一个连贯的、跨浏览器的 Javascript API,它在浏览器和 Web 服务器之间创建了一个低延迟、全双工、跨域的通信通道
在底层,SockJS 尝试首先使用原生 WebSockets。如果失败,它可以使用各种特定于浏览器的传输协议,并通过类似 WebSocket 的抽象来呈现它们。
SockJS: https://github.com/sockjs/sockjs-client
SockJS对象包含几个常用的实用方法:
onopen,和服务端讲了连接后的回调方法
onmessage,服务端返回消息时的回调方法
onclose,和服务端断开连接的回调方法
send,发送消息给服务端
close,断开和服务端的连接
引入SockJS库。在connect()方法中,通过new SockJS(/connect)和服务端建立Socket通信
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket客户端</title>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
</head>
<body>
<div style="width:50%;margin:auto;border-style:solid;border-color:aqua;border-width: 1px">
<input type="text" placeholder="请输入发送的内容" id="text"/>
<input type="button" value="连接" class="btn btn-info" onclick="connect()"/>
<input type="button" value="发送" class="btn btn-success" onclick="sent()"/>
<input type="button" value="断开" class="btn btn-danger" onclick="disconnect()"/>
<div id="log">
<p>聊天记录:</p>
</div>
</div>
<script type="text/javascript">
let text = document.querySelector('#text');
let logDiv = document.querySelector("#log");
let ws = null;
function connect() {
let url = "/webSocket";
ws = new SockJS(url);
ws.onopen = function () {
log('与服务端连接成功!');
};
ws.onmessage = function (event) {
log('服务端:' + event.data);
};
ws.onclose = function () {
log('与服务端断开连接!')
}
}
function sent() {
if (ws != null) {
ws.send(text.value);
log('客户端:' + text.value);
} else {
log('请先建立连接!')
}
}
function disconnect() {
if (ws != null) {
ws.close();
ws = null;
} else {
log('连接已断开!')
}
}
function log(value) {
let content = document.createElement('p');
content.innerHTML = value;
logDiv.appendChild(content);
text.value = '';
}
</script>
</body>
</html>