在开发Web应用程序时,有时我们需要将服务器事件下推到已连接的客户端。 但是,HTTP并非旨在允许这样做。 客户端打开与服务器的连接并请求数据。 服务器不会打开与客户端的连接并推送数据。
为了解决此限制,建立了一种轮询模式,其中网页将间歇地轮询服务器是否有任何新事件。 这种模式不理想,因为它增加了HTTP开销,仅与轮询速率一样快,并在服务器上造成了不必要的负载。
幸运的是,随着HTML5的出现,WebSocket出现了。 WebSocket协议使浏览器和Web服务器之间的交互具有较低的开销。 在此博客中,我们将介绍Websockets API并展示如何使用Spring Boot实现Websockets。
抢救HTML5!
WebSocket通过浏览器和服务器之间的单个连接提供全双工通信。 它没有HTTP的开销,并允许服务器将消息实时推送到客户端。
WebSocket API实际上非常简单。 创建一个WebSocket
对象,附加事件侦听器,并发送消息。
这是一个例子:
var socket = new WebSocket('ws://' + window.location.host + '/my-websocket-endpoint');
// Add an event listener for when a connection is open
socket.onopen = function() {
console.log('WebSocket connection opened. Ready to send messages.');
// Send a message to the server
socket.send('Hello, from WebSocket client!');
};
// Add an event listener for when a message is received from the server
socket.onmessage = function(message) {
console.log('Message received from server: ' + message);
};
Spring靴
Spring对与WebSockets的接口提供了出色的支持。
首先,我们需要创建一个扩展Spring类TextWebSocketHandler
类。
public class MyMessageHandler extends TextWebSocketHandler {
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// The WebSocket has been closed
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
// The WebSocket has been opened
// I might save this session object so that I can send messages to it outside of this method
// Let's send the first message
session.sendMessage(new TextMessage("You are now connected to the server. This is the first message."));
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {
// A message has been received
System.out.println("Message received: " + textMessage.getPayload());
}
}
接下来,我们需要配置WebSocket
端点。
@Configuration
@EnableWebSocket
public class WebsocketConfig implements WebSocketConfigurer {
@Bean
public WebSocketHandler myMessageHandler() {
return new MyMessageHandler();
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myMessageHandler(), "/my-websocket-endpoint");
}
}
由于WebSockets API是纯JavaScript,因此您应该能够在大多数前端框架中使用它。 这包括Angular,因为您可以在TypeScript中直接包含JavaScript。
最后的想法
非常简单,它解决了服务器和客户端之间同时进行数据传输的麻烦。 Spring Boot使它变得更加容易。
想要看Websockets的实际应用吗? 在Keyhole,我们已经构建了一个开源工具Trouble Maker ,可以将故障注入到我们的平台中,以便我们可以练习和测试使平台具有弹性的恢复机制。 Trouble Maker具有Angular前端,并利用WebSocket进行一些实时通信。 查看Github Repo尝试一下。