Spring WebSocket

    18

1. WebSocket基础

连接建立流程:

Client                      Server
  |                           |
  |------ HTTP Upgrade ------>|  // 发起升级请求
  |                           |
  |<---- 101 Switching -------|  // 服务器同意升级
  |                           |
  |<===== WebSocket =========>|  // 建立全双工连接

2. Spring WebSocket核心组件

  1. WebSocketHandler
@Component
public class MessageWebSocketHandler extends TextWebSocketHandler {
    // 连接建立时
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        String userId = getUserId(session);
        sessions.put(userId, session);
    }
    
    // 处理消息
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) {
        // 处理接收到的消息
    }
    
    // 连接关闭时
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        sessions.remove(getUserId(session));
    }
}
  1. WebSocketConfigurer
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler, "/ws")
               .addInterceptors(handshakeInterceptor)
               .setAllowedOrigins("*");
    }
}

3. 会话管理

  1. Session存储
public class MessageWebSocketHandler {
    // 使用线程安全的Map存储会话
    private final Map<String, WebSocketSession> sessions = 
        new ConcurrentHashMap<>();
        
    // 发送消息
    public void sendMessage(String userId, String message) {
        WebSocketSession session = sessions.get(userId);
        if (session != null && session.isOpen()) {
            session.sendMessage(new TextMessage(message));
        }
    }
}
  1. 心跳检测
@Configuration
public class WebSocketConfig {
    @Bean
    public ServletServerContainerFactoryBean createWebSocketContainer() {
        ServletServerContainerFactoryBean container = 
            new ServletServerContainerFactoryBean();
        // 设置消息大小限制
        container.setMaxTextMessageBufferSize(8192);
        // 设置心跳超时时间
        container.setMaxSessionIdleTimeout(60000L);
        return container;
    }
}

4. 消息类型

  1. TextMessage
// 发送文本消息
session.sendMessage(new TextMessage("Hello"));

// 接收文本消息
@Override
protected void handleTextMessage(WebSocketSession session, 
                               TextMessage message) {
    String payload = message.getPayload();
}
  1. BinaryMessage
// 发送二进制消息
byte[] bytes = ...;
session.sendMessage(new BinaryMessage(bytes));

// 接收二进制消息
@Override
protected void handleBinaryMessage(WebSocketSession session, 
                                 BinaryMessage message) {
    byte[] payload = message.getPayload().array();
}

5. 安全处理

  1. 握手拦截
public class WebSocketInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(...) {
        // 验证token
        String token = request.getHeaders().get("token").get(0);
        if (!isValidToken(token)) {
            return false; // 拒绝连接
        }
        return true;
    }
}
  1. 异常处理
@Override
public void handleTransportError(WebSocketSession session, 
                               Throwable exception) {
    log.error("WebSocket传输错误", exception);
    if (session.isOpen()) {
        session.close();
    }
}

6. STOMP支持

Spring也支持STOMP协议:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");  // 广播消息前缀
        config.setApplicationDestinationPrefixes("/app"); // 应用前缀
    }
}

7. 最佳实践

  1. 错误处理
try {
    session.sendMessage(new TextMessage(message));
} catch (IOException e) {
    log.error("发送消息失败", e);
    sessions.remove(userId);
}
  1. 消息序列化
// 发送JSON消息
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(messageObject);
session.sendMessage(new TextMessage(json));
  1. 连接状态检查
public void sendMessage(String userId, String message) {
    WebSocketSession session = sessions.get(userId);
    if (session != null && session.isOpen()) {
        try {
            session.sendMessage(new TextMessage(message));
        } catch (IOException e) {
            log.error("发送失败", e);
            closeSession(session);
        }
    }
}

这些是Spring WebSocket的主要知识点,在实际应用中要根据具体需求选择合适的实现方式。

Comments | 0 评论
消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息