首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 整合 WebSocket 實現消息推送完整教程

     編輯:Java 相關知識

WebSocket 協議基礎

WebSocket 提供全雙工長連接,解決 HTTP 輪詢高延遲、高開銷問題。握手階段升級 HTTP 協議(Upgrade: websocket),後續雙向幀傳輸,無需重複 Header。

Spring 整合方案對比

方案特點適用場景
Spring WebSocket (標準 JSR-356)註解驅動、STOMP 子協議、SockJS 降級企業級應用、消息代理、廣播/點對點
Spring WebFlux WebSocket響應式、非阻塞、函數式路由高併發、Reactive 技術棧
Netty 自定義完全控制、極致性能IM、遊戲、IoT 网關

本文採用 Spring Boot + Spring WebSocket + STOMP + SockJS 方案。

依賴配置

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>webjars-locator-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>sockjs-client</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>stomp-websocket</artifactId>
        <version>2.3.4</version>
    </dependency>
</dependencies>

配置類

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        // 簡單內存代理:/topic 廣播、/queue 點對點
        registry.enableSimpleBroker("/topic", "/queue");
        // 應用目標前綴:客戶端發送 @MessageMapping 路徑
        registry.setApplicationDestinationPrefixes("/app");
        // 用戶專屬隊列前綴
        registry.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 原生 WebSocket 端點
        registry.addEndpoint("/ws").setAllowedOriginPatterns("*");
        // SockJS 降級端點(兼容舊瀏覽器、代理)
        registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new AuthChannelInterceptor()); // 鑒權攔截器
    }
}

消息控制器

消息模型

public class ChatMessage {
    private String content;
    private String sender;
    private MessageType type; // CHAT, JOIN, LEAVE
    private Instant timestamp;
    // getter/setter
}

public class PrivateMessage {
    private String toUser;
    private String content;
    // getter/setter
}

public enum MessageType { CHAT, JOIN, LEAVE }

鑒權攔截器

public class AuthChannelInterceptor implements ChannelInterceptor {
    @Override
    public Message preSend(Message message, MessageChannel channel) {
        StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
        if (StompCommand.CONNECT.equals(accessor.getCommand())) {
            // 從 Header 獲取 Token
            String token = accessor.getFirstNativeHeader("Authorization");
            if (token != null && token.startsWith("Bearer ")) {
                token = token.substring(7);
                // 驗證 Token 並設置 Principal
                UserDetails user = tokenService.validate(token);
                if (user != null) {
                    accessor.setUser(new StompPrincipal(user.getUsername()));
                } else {
                    throw new InvalidTokenException("Token 無效");
                }
            } else {
                throw new MissingTokenException("缺少 Authorization Header");
            }
        }
        return message;
    }
}

前端接入 (JavaScript)

<script src="/webjars/sockjs-client/1.6.1/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/2.3.4/stomp.min.js"></script>


生產環境擴展

  1. 外部消息代理:替換 enableSimpleBroker 為 enableStompBrokerRelay("/topic", "/queue") 連接 RabbitMQ/ActiveMQ/Kafka,支持集群水平擴展。
  2. 心跳機制:配置 setHeartbeatValue(new long[]{10000, 10000}) 客戶端/服務端心跳間隔。
  3. 消息持久化:配合 Redis/Kafka 存儲離線消息,用戶上線推送。
  4. 分布式 Session:Spring Session + Redis 共享 WebSocket 會話。
  5. 安全加固:WSS (WebSocket over TLS)、CSRF 保護、速率限制。

常見問題排查

現象原因解決
握手 403CSRF 保護攔截、Origin 不匹配配置 setAllowedOriginPatterns("*")、關閉 CSRF 或配置 CsrfTokenRepository
SockJS 降級輪詢代理/防火牆阻斷 WebSocket檢查 Nginx proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade;
用戶收不到私聊Principal 未正確設置、目標用戶未連接檢查 AuthChannelInterceptor、用戶在線狀態
消息丟失SimpleBroker 內存隊列溢出遷移外部 Broker、配置持久化

總結

Spring WebSocket + STOMP 提供開箱即用的消息推送能力:@MessageMapping 處理業務、SimpMessagingTemplate 主動推送、@SendTo 廣播、convertAndSendToUser 私聊。配合 SockJS 兼容性、外部 Broker 集群化、鑒權攔截器,可構建企業級實時通訊系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved