WebSocket 是一种通信协议,提供全双工、实时通信的能力,特别适合用于需要频繁数据交换的应用程序,如在线聊天、实时通知、游戏等。
STOMP(Streaming Text Oriented Messaging Protocol)是一种简单的、基于文本的消息协议,旨在支持多种消息传递和通讯模式。它特别适用于 WebSocket 的场景,常用于实现实时消息推送和通信。
1. 文本导向
STOMP 使用文本格式,使其易于调试和理解。消息和命令都是以可读的文本形式进行传输,通常是以行的方式表示。
2. 基于客户端-服务器模型
STOMP 使用客户端-服务器架构,其中客户端通过 STOMP 连接到消息代理(broker),并可以发布(send)、订阅(subscribe)和接收(receive)消息。
STOMP 支持两种主要的消息传递模型:
- 主题(Topic):一对多的消息传递模式,消息会广播给所有订阅该主题的客户端。
- 队列(Queue):一对一的消息传递模式,消息被发送到特定的队列,只有一个消费者可以接收该消息。
Spring Boot 应用程序中使用 WebSocket
1.导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 其他依赖 -->
</dependencies>
2. 创建 WebSocket 服务器端点
创建一个 WebSocket 端点类,例如 ChatEndpoint
。注意,使用 @ServerEndpoint
注解需要添加 javax.websocket
相关的依赖。
package com.example.websocket;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
@ServerEndpoint("/chat") // WebSocket 端点,跟前端保持一致
public class ChatEndpoint {
private static Set<Session> clients = new CopyOnWriteArraySet<>(); // 存储客户端连接
@OnOpen
public void onOpen(Session session) {
clients.add(session); // 添加新连接
System.out.println("New connection: " + session.getId());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message from client: " + message);
// 广播消息给所有连接的客户端
for (Session client : clients) {
if (!client.equals(session)) { // 不发送给发送者
try {
client.getBasicRemote().sendText(message); // 发送消息
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@OnClose
public void onClose(Session session) {
clients.remove(session); // 移除关闭的连接
System.out.println("Connection closed: " + session.getId());
}
}
3. 创建配置类
接下来,创建一个配置类,并在其中定义 ServerEndpointExporter
Bean:
package com.example.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter(); // 允许 @ServerEndpoint 注解的类被扫描
}
}
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Chat</title>
</head>
<body>
<h1>WebSocket Chat</h1>
<input type="text" id="message" placeholder="Enter your message..."/>
<button onclick="sendMessage()">Send</button>
<div id="chat" style="border: 1px solid #ccc; height: 300px; overflow-y: scroll;"></div>
<script>
const websocket = new WebSocket("ws://localhost:8080/chat"); // 连接到 WebSocket 服务器
websocket.onopen = function() {
console.log("Connected to the WebSocket server.");
};
websocket.onmessage = function(event) {
showMessage(event.data); // 显示收到的消息
};
websocket.onclose = function() {
console.log("Disconnected from the WebSocket server.");
};
function sendMessage() {
const messageInput = document.getElementById('message');
const message = messageInput.value;
websocket.send(message); // 发送消息
messageInput.value = ''; // 清空输入框
}
function showMessage(message) {
const chatDiv = document.getElementById('chat');
chatDiv.innerHTML += "<div>" + message + "</div>"; // 更新聊天记录
chatDiv.scrollTop = chatDiv.scrollHeight; // 滚动到最新消息
}
</script>
</body>
</html>