简介
WebSocket是一种在单个TCP连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
既然是一个长连接,那么对于比较时效性(如聊天)或者需要推送的场景就可以使用WebSocket来实现,服务端不再是等待客户端的请求而可以主动推送消息给客户端。同时也减少了资源的开销,因为之前通过HTTP的做法通常都是轮询来实现时效性,这种做法需要不断发起HTTP请求,而使用WebSocket长连接减少了连接的开销,建立连接之后只关心数据本身。
基于SpringBoot的WebSocket支持
Spring Websocket介绍
Spring WebSocket通过注册不同WebSocketHandler
来处理不同的消息通道,消息处理具体在WebSocketHandler
里面实现,通常都是通过实现AbstractWebSocketHandler
类来自定义自己的处理器。
maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
配置&使用
- WebSocketConfig
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册自定义消息处理,消息路径为`/ws/foo`
registry.addHandler(new FooWebSocketHandler(),"/ws/foo").setAllowedOrigins("*");
}
}
- 自定义处理器 FooWebSocketHandler
public class FooWebSocketHandler extends TextWebSocketHandler {
private final static List<WebSocketSession> sessions = new ArrayList<>();
public static List<WebSocketSession> allSessions(){
return new ArrayList<>(sessions);
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//在这里自定义消息处理...
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//保存所有会话
sessions.add(session);
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
if(!sessions.isEmpty()){
// remove session after closed
for (Iterator<WebSocketSession> iterator = sessions.iterator();iterator.hasNext();){
WebSocketSession s = iterator.next();
if(session.getId().equals(s.getId())){
iterator.remove();
}
}
}
}
}
- 实现简单消息推送给所有在线用户
for (WebSocketSession session : FooWebSocketHandler.allSessions()) {
try {
TextMessage message = new TextMessage("${message body}").getBytes());
if(session.isOpen()){
session.sendMessage(message);
}
} catch (IOException e) {
throw new RuntimeException(e.getMessage(),e);
}
}
- 客户端与服务端连接交互(JavaScript为例)
var ws = new WebSocket('ws://localhost:8080/ws/foo')
ws.onmessage = function(event) {
var data = event.data;
console.log(data)
};
- nginx配置WebSocket方向代理
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server localhost:8080;
}
server{
location ~ /ws {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
}
网友评论