前言
早期,很多网站为了实现推送技术,所用的技术都是轮询。轮询是指由浏览器每隔一段时间(如每秒)向服务器发出HTTP
请求,然后服务器返回最新的数据给客户端。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP
请求与回复可能会包含较长的头部,其中真正有效的数据可能只是很小的一部分,所以这样会消耗很多带宽资源。比较新的轮询技术是Comet。这种技术虽然可以实现双向通信,但仍然需要反复发出请求。而且在Comet
中普遍采用的HTTP长连接也会消耗服务器资源。在这种情况下,HTML5
定义了WebSocket
协议,在WebSocket API
中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输,这样能更好的节省服务器资源和带宽,并且能够更实时地进行通讯(以上内容来自维基百科)。
Websocket
使用ws
或wss
的统一资源标志符(URI)。其中wss
表示使用了TLS的Websocket
。如:
ws://example.com/wsapi
wss://secure.example.com/wsapi
下面就通过一个简单的例子介绍如何在SpringBoot
中集成WebSocket
,只展示WebSocket
的核心配置,完整代码已上传到GitHub(由于下篇博客对本文的代码有改造,在测试的时候需要输入 https://localhost 而不是 http://localhost:8080,同时本地需要先创建一个 blog 数据库和 user 表并添加测试数据):
效果展示
在展示代码配置前,先展示一下效果(已提前登录了三个用户):
具体的代码配置
- 引入依赖
首先需要在pom.xml
中引入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- 配置
ServerEndpointExporter
的Bean
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
- 配置服务器终端
@Component
@ServerEndpoint("/websocket")
public class WebSocketServer {
private Session session;
// 保存所有的客户端连接
private static final Map<String, WebSocketServer> connections = new LinkedHashMap<>();
@OnOpen
public void onOpen(Session session) {
this.session = session;
connections.put(session.getId(), this);
}
@OnMessage
public void onMessage(String message, Session session) {
try {
sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
}
@OnError
public void onError(Throwable error, Session session) throws Throwable {
throw error;
}
@OnClose
public void onClose() {
connections.remove(session.getId());
}
public void sendMessage(String message) throws IOException {
session.getBasicRemote().sendText(message);
}
// 广播方法(实现消息群发)
public static void broadcast(String message) {
connections.forEach((k, v) -> {
try {
v.sendMessage(message);
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
- 配置群发通知接口
@RestController
public class BroadcastController {
@PostMapping("/broadcast")
public void broadcast(@RequestBody String msg){
WebSocketServer.broadcast(msg);
}
}
- 客户端配置
客户端简单使用Vue
框架,没有使用单文件组件形式,客户端连接代码如下:
let socket = new WebSocket("ws://localhost:8080/websocket")
socket.onerror = err => {
console.log(err)
}
socket.onopen = event => {
console.log(event)
}
socket.onmessage = event => {
// 这里接受服务端发送的信息
vue.$data.toast = {
isShow: true,
msg: JSON.parse(event.data).msg
}
}
socket.onclose = () => {
console.log("连接关闭")
}
完成以上简单配置后,只要调用了群发信息的接口,客户端就可以通过onmessage
函数来处理接收到的信息。
- 浏览器控制台测试
如果想要尽快测试结果,不想写前端代码,可以直接在控制台中输入以下代码(对5中的代码稍作修改):
然后在新建一个页面并地址栏中输入http://localhost:8080/broadcast?msg=1234567
并回车(记得将4中的PostMapping
改为GetMapping
,并删掉@RequestBody
),输完回车后,在返回上一个界面查看控制台,即可发现接收信息:
总结
本文简单介绍了如何通过SpringBoot
集成WebSocket
实现群发信息的功能,本文只讲解了WebSocket
的基本使用,也只使用了ws
,在下篇文章将会介绍如何使用加密的wss
协议。