WebSocket 在 SpringBoot 中的实践

传统的服务端-客户端通信协议为HTTP,但是其只能先由客户端发起请求,且为短连接。所以,服务端无法按需向客户端推送数据,只能让客户端依靠轮询的方式来请求新数据。而在HTML 5标准中的WebSocket技术则恰好可以解决这个问题,其由客户端发起连接为长连接,服务端和客户端可以一直保存这个长连接。本文简要介绍在SpringBoot下的WebSocket实践

abstract

实践入门

在pom.xml中添加WebSocket依赖

1
2
3
4
5
6
<!-- WebSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>

根据Spring官方的文档,编写一个Java Bean的配置类来创建WebSocket的Handler Bean,其需继承 WebSocketConfigurer 类,并通过重写 registerWebSocketHandlers 方法实现将WebSocket 的 Handler 和 Websocket的请求路径进行绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {

webSocketHandlerRegistry.addHandler(webSocketHandler(),"/testHandler").setAllowedOrigins("*");
// 不使用 setAllowedOrigins 方法,服务端将不会接收跨域请求,后文将详述
//webSocketHandlerRegistry.addHandler(webSocketHandler(),"/testHandler");
}

@Bean
public TextWebSocketHandler webSocketHandler() {
return new Handler1();
}
}

Note:

  • 在该类上添加 @EnableWebSocket 注解,否则无法启用WebSocket

根据Spring官方的文档,按照上面的配置写一个用于处理WebSocket的Handler1类即可,其可继承TextWebSocketHandler类,该类提供了WebSocket中一些基本的操作方法,我们只需按需重写相关方法即可,实现对WebSocket的连接管理和消息处理功能,示例代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Component
public class Handler1 extends TextWebSocketHandler {
// js 调用 websocket.onopen时 ,服务端即会调用该方法,建立连接
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
super.afterConnectionEstablished(session);
System.out.println("服务器建立连接 .........");
}

// js 调用 websocket.send 发送消息时,服务端即会调用该方法,处理客户端的消息
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
super.handleTextMessage(session, message);
System.out.println("服务器收到消息:" + message.getPayload());
// 发送消息给客户端
session.sendMessage(new TextMessage("Hello World"));
}

// js 调用 websocket.close时, 服务端即会调用该方法,关闭当前客户端的连接
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("服务器关闭连接");
}
}

测试结果如下:

figure 1.jpeg

Status Code: 403 跨域请求失败

当浏览器地址栏的url 和 WebSocket url不一致时,如下图所示。地址栏的url为localhost而WebSocket的url为127.0.0.1时,如果我们不使用setAllowedOrigins() 方法,会发现WebSocket请求失败,其状态码为403,从Server的日志中我们也可以看出,由于跨域问题,服务端拒绝客户端的请求。所以,只需按前文所述,调用 setAllowedOrigins(“*“) 即可让服务端响应跨域请求

figure 2.jpeg

figure 3.jpeg

参考

Spring WebSocket 官方文档

0%