WebSocket API
Spring Framework 提供了一个 WebSocket API,你可以使用它来编写处理 WebSocket 消息的客户端和服务器端应用程序。
WebSocketHandler
创建一个 WebSocket 服务器非常简单,只需实现 WebSocketHandler,或者更常见的是继承 TextWebSocketHandler 或 BinaryWebSocketHandler。以下示例使用 TextWebSocketHandler:
public class MyHandler extends TextWebSocketHandler {
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}
}class MyHandler : TextWebSocketHandler() {
override fun handleTextMessage(session: WebSocketSession, message: TextMessage) {
// ...
}
}你可以使用专用的 WebSocket 编程式配置或 XML 命名空间将上述 WebSocket 处理程序映射到特定的 URL:
@Configuration
@EnableWebSocket
public class WebSocketConfiguration implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}@Configuration
@EnableWebSocket
class WebSocketConfiguration : WebSocketConfigurer {
override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
registry.addHandler(myHandler(), "/myHandler")
}
@Bean
fun myHandler(): WebSocketHandler {
return MyHandler()
}
}<websocket:handlers>
<websocket:mapping path="/myHandler" handler="myHandler"/>
</websocket:handlers>
<bean id="myHandler" class="org.springframework.docs.web.websocket.MyHandler"/>WebSocket 握手
自定义初始 HTTP WebSocket 握手请求的最简单方法是通过 HandshakeInterceptor。你可以使用这种拦截器来阻止握手或使任何属性对 WebSocketSession 可用。以下示例使用内置拦截器将 HTTP 会话属性传递给 WebSocket 会话:
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(new MyHandler(), "/myHandler")
.addInterceptors(new HttpSessionHandshakeInterceptor());
}override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
registry.addHandler(MyHandler(), "/myHandler")
.addInterceptors(HttpSessionHandshakeInterceptor())
}部署与服务器配置
服务器配置
你可以配置底层 WebSocket 服务器的属性,例如输入消息缓冲大小、空闲超时等。
对于 Jakarta WebSocket 服务器,可以添加 ServletServerContainerFactoryBean:
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}@Bean
fun createWebSocketContainer() = ServletServerContainerFactoryBean().apply {
maxTextMessageBufferSize = 8192
maxBinaryMessageBufferSize = 8192
}允许的来源 (Allowed Origins)
默认情况下,WebSocket 和 SockJS 仅接受同源请求。你可以允许所有来源或指定的列表:
registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("https://mydomain.com");registry.addHandler(myHandler(), "/myHandler").setAllowedOrigins("https://mydomain.com")补充教学
1. 生命周期方法
在 WebSocketHandler 中,除了处理消息,你还可以重写:
afterConnectionEstablished: 连接建立后调用,通常用于存储 Session。afterConnectionClosed: 连接关闭后调用,用于清理资源。
2. 线程安全问题
基础的 WebSocket Session 不是线程安全的。如果你需要从多个线程并发发送消息,请使用 ConcurrentWebSocketSessionDecorator 包装原始 Session。
3. 处理二进制数据
如果你的应用需要处理图片或文件流,请继承 BinaryWebSocketHandler 并重写 handleBinaryMessage 方法。