36. Spring Boot如何支持WebSocket?如何配置WebSocket端点?
在Spring Boot中,WebSocket支持是通过Spring的spring-websocket
模块实现的。WebSocket提供了在客户端和服务器之间建立全双工通信通道的能力,适用于实时更新、消息推送等场景。Spring Boot简化了WebSocket的配置过程,使得开发者可以快速集成WebSocket功能。下面是如何在Spring Boot中支持WebSocket,以及如何配置WebSocket端点的详细说明。
1. 引入依赖
首先,在pom.xml
中引入Spring WebSocket的依赖。如果你使用的是Spring Boot Starter WebSocket,这个依赖将自动包含在内。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2. 配置WebSocket端点
要在Spring Boot中启用WebSocket支持并配置WebSocket端点,通常需要创建一个配置类并实现WebSocketConfigurer
接口。
2.1 基本的WebSocket配置
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyWebSocketHandler(), "/ws")
.setAllowedOrigins("*"); // 允许跨域请求
}
}
在这个配置类中:
@EnableWebSocket
:启用WebSocket支持。registerWebSocketHandlers
:在这个方法中注册WebSocket处理器和端点。addHandler(new MyWebSocketHandler(), "/ws")
:将WebSocket处理器MyWebSocketHandler
绑定到/ws
端点。客户端可以通过这个URL连接到WebSocket服务器。setAllowedOrigins("\*")
:允许跨域WebSocket连接,*
表示允许所有域。你可以根据需求限制特定的域。
2.2 创建WebSocket处理器
接下来,需要创建一个WebSocket处理器类,实现WebSocketHandler
接口,用于处理WebSocket连接、消息和断开连接等事件。
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
public class MyWebSocketHandler extends TextWebSocketHandler {
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("New WebSocket connection established: " + session.getId());
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("Received message: " + message.getPayload());
session.sendMessage(new TextMessage("Message received: " + message.getPayload()));
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("WebSocket connection closed: " + session.getId());
}
}
在这个处理器类中:
afterConnectionEstablished
:在客户端与服务器建立WebSocket连接后调用,可以用来初始化会话或发送欢迎消息。handleTextMessage
:处理从客户端接收的文本消息,并可以选择性地向客户端发送响应。afterConnectionClosed
:在WebSocket连接关闭后调用,可以用来清理资源或记录日志。
3. 使用STOMP协议支持消息广播
对于更复杂的WebSocket应用,特别是需要广播消息或处理主题订阅的情况,Spring提供了对STOMP协议的支持。
3.1 配置STOMP端点
首先,需要更新WebSocket配置以支持STOMP协议。
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-stomp")
.setAllowedOrigins("*")
.withSockJS(); // 使用SockJS回退机制
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic", "/queue");
registry.setApplicationDestinationPrefixes("/app");
}
}
在这个配置类中:
@EnableWebSocketMessageBroker
:启用WebSocket消息代理功能,并支持STOMP协议。registerStompEndpoints
:注册STOMP端点,客户端通过这个URL连接到WebSocket服务器,使用SockJS来支持回退选项,以便在浏览器不支持WebSocket时回退到其他技术。configureMessageBroker
:配置消息代理,这里使用了简单的内存代理,支持主题(/topic
)和队列(/queue
)消息广播。setApplicationDestinationPrefixes("/app")
定义了应用程序发送消息的前缀。
3.2 创建消息处理器
然后,创建一个控制器类,使用@MessageMapping
来处理来自客户端的消息。
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class GreetingController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public String handleGreeting(String message) {
return "Hello, " + message + "!";
}
}
在这个控制器类中:
@MessageMapping("/hello")
:映射客户端发送到/app/hello
的消息(注意前缀/app
由setApplicationDestinationPrefixes
配置)。@SendTo("/topic/greetings")
:将处理后的消息广播到/topic/greetings
,订阅这个主题的所有客户端将收到消息。
4. 客户端代码示例
客户端可以使用JavaScript来连接和通信,下面是一个简单的HTML页面示例。
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Test</title>
<script src="https://cdn.jsdelivr.net/sockjs/1/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/stompjs@2.3.3/lib/stomp.min.js"></script>
</head>
<body>
<h2>WebSocket Test</h2>
<button onclick="connect()">Connect</button>
<button onclick="disconnect()">Disconnect</button>
<button onclick="sendMessage()">Send Message</button>
<div id="messages"></div>
<script>
var stompClient = null;
function connect() {
var socket = new SockJS('/ws-stomp');
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
console.log('Connected: ' + frame);
stompClient.subscribe('/topic/greetings', function (greeting) {
showMessage(greeting.body);
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
console.log("Disconnected");
}
function sendMessage() {
stompClient.send("/app/hello", {}, "World");
}
function showMessage(message) {
var messagesDiv = document.getElementById('messages');
messagesDiv.innerHTML += "<div>" + message + "</div>";
}
</script>
</body>
</html>
在这个客户端代码中:
SockJS('/ws-stomp')
:使用SockJS连接到WebSocket端点/ws-stomp
。Stomp.over(socket)
:使用STOMP协议建立连接。stompClient.subscribe('/topic/greetings', ...)
:订阅/topic/greetings
主题,当服务器发送消息时,客户端将接收到并显示在页面上。stompClient.send("/app/hello", {}, "World")
:向服务器发送消息,服务器处理后广播到/topic/greetings
。
5. 总结
Spring Boot对WebSocket的支持非常强大和灵活,通过简单的配置就可以快速集成WebSocket功能,满足实时通信的需求。对于需要消息广播和主题订阅的应用,可以使用STOMP协议和消息代理功能。结合SockJS可以提供更好的浏览器兼容性和回退机制。