-
添加依赖 :在
pom.xml
文件中添加Spring Boot的WebSocket依赖。<dependencies> <!-- Spring Boot Starter Websocket --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> </dependencies>
-
WebSocket配置类 (
WebSocketConfig.java
):import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.*;@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {@Override public void registerStompEndpoints(StompEndpointRegistry registry) { //这个代表了前端需要通过/ws路径来建立连接 registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { //这个你就把它当作创建了"/topic", "/queue"这两个频道,然后前端建立连接后 //可以监听这两个频道,后端发送消息到这其中频道后,前端可以接收到 registry.enableSimpleBroker("/topic", "/queue"); //这个代表前端可以通过/user开头的地址,来给服务端发送消息,服务端可以用 //@MessageMapping注解来接收消息 // @MessageMapping("/sendMessage") 例如这样写,前端就需要通过/user/sendMessage来给后 //端的这个方法发送消息 registry.setUserDestinationPrefix("/user"); }
}
WebSocket控制器 (WebSocketController.java
):
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
//接收客户端向/user/sendMessage这个地址发送的消息
@MessageMapping("/sendMessage")
//把接收来的这个消息发送到所有订阅/topic/messages地址的客户端
@SendTo("/topic/messages")
public String processMessageFromClient(String message) {
return "Server response: " + message;
}
}
让你更便于理解,我这么写:
当客户端通过 /sendMessage
发送消息时,processMessageFromClient
方法会被调用,并将消息传递给 sendToTopicMessages
方法。sendToTopicMessages
方法会返回一个格式化的响应消息,该消息会被发送到 /topic/messages
主题(订阅频道)。
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class WebSocketController {
@MessageMapping("/sendMessage")
public String processMessageFromClient(String message) {
// 调用 sendToTopicMessages 并使用其返回值
return sendToTopicMessages(message);
}
@SendTo("/topic/messages")
public String sendToTopicMessages(String message) {
// 返回服务器响应的消息
return "Server response: " + message;
}
}
当然你也可以不适用@SendTo注解来向订阅地址发送消息。
SimpMessagingTemplate
是 Spring Framework 中的一个类,它提供了向 WebSocket 客户端发送消息的多种方法。
以下是一些主要方法:
1. **convertAndSend**:这是最常用的方法,用于将消息转换并发送到指定目的地。它支持发送文本消息、二进制消息和对象消息等。例如,`convertAndSend("/topic/greetings", "Hello World!")` 会向所有订阅了 `/topic/greetings` 的客户端发送一条文本消息 。
2. **convertAndSendToUser**:此方法允许你向特定用户发送消息。它需要用户的标识符、目的地和消息内容。例如,`convertAndSendToUser("user1", "/queue/notifications", message)` 会向用户 `user1` 发送消息 。
3. **setUserDestinationPrefix**:设置用于针对特定用户的目标地址的前缀。默认值是 `"/user/"`。此方法通常与 `convertAndSendToUser` 结合使用,以确保消息发送到正确的用户端点 。
4. **getMessageChannel**:返回配置的消息通道,该通道用于发送消息 。
5. **setSendTimeout** 和 **getSendTimeout**:用于设置和获取发送操作的超时时间(以毫秒为单位)。
6. **send**:发送一个 `Message` 对象到指定的目的地。如果消息头中已经包含了目的地,则消息将直接发送到该目的地;如果没有,则会发送到配置的默认目的地 。
`SimpMessagingTemplate` 的使用需要在项目中添加 Spring Boot 的 WebSocket 依赖 `spring-boot-starter-websocket` 。通过注入 `SimpMessagingTemplate` 的实例,你可以在 Spring Boot 应用程序的任何地方发送消息,甚至不必首先接收一条消息作为前提 。
在实际开发中,`SimpMessagingTemplate` 可以用于实现如聊天应用、实时数据推送等需要 WebSocket 通信的功能。使用时,可以通过配置文件或注解来启用 WebSocket 支持,并利用 `SimpMessagingTemplate` 的方法来处理消息的发送 。
前端页面 (index.html
):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket Demo</title>
<script src="https://cdn.jsdelivr.net/npm/sockjs-client/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs/lib/stomp.min.js"></script>
</head>
<body>
<h1>WebSocket Demo</h1>
<input type="text" id="message" placeholder="Type a message">
<button onclick="sendMessage()">Send</button>
<h2>Messages</h2>
<ul id="messages"></ul>
<script type="text/javascript">
const socket = new SockJS('/ws');
const stompClient = Stomp.over(socket);
let connected = false;
function connect() {
stompClient.connect({}, frame => {
connected = true;
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/messages', message => displayMessage(message));
});
}
function sendMessage() {
const messageInput = document.getElementById('message');
if (connected) {
stompClient.send("/app/sendMessage", {}, messageInput.value);
messageInput.value = '';
} else {
alert("Please connect first!");
}
}
function displayMessage(message) {
const messagesList = document.getElementById('messages');
const messageItem = document.createElement('li');
messageItem.textContent = message.body;
messagesList.appendChild(messageItem);
}
socket.onclose = () => {
connected = false;
console.log("Disconnected");
};
window.onload = connect; // Connect when the page loads
</script>
</body>
</html>
这样你打开html页面,可以多开几个浏览器。
然后在任意页面发送消息,其他浏览器都会接收并且显示出来,包括发送方的页面也会显示。因为大家都订阅了/topic/messages频道