🎬 HoRain 云小助手个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

🧩 两种实现方式概览

🔧 方式一:使用STOMP子协议

⚙️ 方式二:使用原生WebSocket API

🚀 进阶考虑与最佳实践

💎 核心对比与选择


在 Spring Boot 中集成 WebSocket 来构建实时应用非常方便。下面是一个清晰的指南,帮助你理解两种主要的实现方式及其核心步骤。

🧩 两种实现方式概览

Spring Boot 集成 WebSocket 主要有两种方式,其核心区别在于协议的层级不同。下面的流程图可以帮你快速了解这两种路径以及如何选择。

flowchart TD
    A[开始:集成Spring Boot WebSocket] --> B{选择实现方式}
    
    B -->|需要更高级消息模式<br>(如发布-订阅)| C[方式一:使用STOMP]
    B -->|需要底层控制<br>或自定义协议| D[方式二:使用原生WebSocket API<br>(或SockJS)]
    
    C --> E[步骤:配置消息代理];
    E --> F[步骤:创建消息控制器];
    F --> G[前端:使用STOMP客户端];
    
    D --> H[步骤:实现WebSocketHandler];
    H --> I[步骤:注册处理器];
    I --> J[前端:使用原生WebSocket<br>或SockJS];
    
    G & J --> K[完成集成,实现实时通信]

简单来说:

  • 如果你希望像使用消息队列(如发布-订阅)一样处理实时消息,或者前端希望使用更简单的消息模型,STOMP​ 是不错的选择。

  • 如果你需要直接控制通信细节,或者与使用自定义协议的现有系统集成,那么原生WebSocket API​ 更适合你。

接下来,我们看看这两种方式的具体步骤。

🔧 方式一:使用STOMP子协议

STOMP 提供了一个基于帧的协议,非常适合常见的消息推送场景,如聊天室、实时通知 。

  1. 添加依赖

    pom.xml中添加 Spring Boot 对 WebSocket 和 STOMP 的支持(通常包含在 spring-boot-starter-websocket中)。

  2. 配置STOMP与消息代理

    创建配置类,启用基于STOMP的消息代理。代理负责将消息路由到订阅了特定目的地的客户端 。

    @Configuration
    @EnableWebSocketMessageBroker // 启用STOMP消息代理
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            // 注册STOMP端点,客户端将连接到此端点,并允许使用SockJS作为备选方案
            registry.addEndpoint("/ws-endpoint").withSockJS();
        }
        @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            // 启用一个简单的基于内存的消息代理,负责将消息路由到以"/topic"开头的目的地
            config.enableSimpleBroker("/topic");
            // 设置应用前缀,所有目的地以"/app"开头的消息都会被路由到@MessageMapping注解的方法
            config.setApplicationDestinationPrefixes("/app");
        }
    }
  3. 创建消息控制器

    像编写Spring MVC控制器一样处理客户端发送的消息 。

    @Controller
    public class MessagingController {
        // 处理发送到"/app/send-message"目的地的消息
        @MessageMapping("/send-message")
        // 将返回值广播给所有订阅了"/topic/messages"的客户端
        @SendTo("/topic/messages")
        public String handleMessage(String message) {
            // 处理消息,这里简单返回
            return "服务器回复: " + message;
        }
    }
  4. 前端连接与通信

    使用 STOMP 客户端库(如 stomp.js)连接和通信 。

    // 使用SockJS建立连接,再使用STOMP协议
    var socket = new SockJS('/ws-endpoint');
    var stompClient = Stomp.over(socket);
    
    stompClient.connect({}, function(frame) {
        // 订阅目的地为"/topic/messages"的消息
        stompClient.subscribe('/topic/messages', function(message) {
            console.log('收到消息: ' + message.body);
        });
        // 发送消息到"/app/send-message"
        stompClient.send("/app/send-message", {}, "你好,服务器!");
    });

⚙️ 方式二:使用原生WebSocket API

这种方式更底层,适合需要精细控制通信过程或使用自定义协议的场景 。

  1. 添加依赖

    同样需要在 pom.xml中添加 spring-boot-starter-websocket依赖 。

  2. 实现WebSocket处理器

    创建一个类继承 TextWebSocketHandlerBinaryWebSocketHandler,处理文本或二进制消息 。

    @Component
    public class MyWebSocketHandler extends TextWebSocketHandler {
        private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
    
        @Override
        public void afterConnectionEstablished(WebSocketSession session) throws Exception {
            sessions.add(session); // 新连接建立,保存session
            session.sendMessage(new TextMessage("连接成功"));
        }
        @Override
        protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
            String payload = message.getPayload(); // 获取客户端消息
            // 处理消息,例如广播给所有连接
            for (WebSocketSession s : sessions) {
                if (s.isOpen()) {
                    s.sendMessage(new TextMessage("收到: " + payload));
                }
            }
        }
        @Override
        public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
            sessions.remove(session); // 连接关闭,移除session
        }
    }
  3. 注册WebSocket处理器

    通过配置类将处理器注册到特定路径 。

    @Configuration
    @EnableWebSocket // 启用WebSocket支持(非STOMP)
    public class WebSocketConfig implements WebSocketConfigurer {
        @Autowired
        private MyWebSocketHandler myWebSocketHandler;
    
        @Override
        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
            // 将自定义的处理器注册到路径"/ws"
            registry.addHandler(myWebSocketHandler, "/ws").setAllowedOrigins("*");
        }
    }
  4. 前端连接

    使用浏览器原生 WebSocket API 连接 。

    var socket = new WebSocket('ws://localhost:8080/ws');
    socket.onopen = function(event) { console.log('连接已建立'); };
    socket.onmessage = function(event) { console.log('收到消息: ' + event.data); };
    socket.send('你好!'); // 发送消息

🚀 进阶考虑与最佳实践

在实际项目中,除了基本功能,还需考虑以下几点:

  • 会话管理:在原生API方式中,需要使用线程安全的集合(如 ConcurrentHashMap)管理 WebSocketSession,以便向特定客户端发送消息或实现广播 。

  • 心跳与健康检查:实现心跳机制(如定时发送Ping/Pong帧)来检测和清理僵死连接 。

  • 安全性

    • 身份验证与授权:可以在握手阶段(如通过拦截器 HandshakeInterceptor)或连接建立后验证用户身份 。结合 Spring Security 可以更好地保护 WebSocket 端点 。

    • 跨域控制:使用 setAllowedOrigins("*")允许所有来源,但在生产环境中应限制为信任的域名 。

    • 使用WSS:在生产环境使用 wss://(WebSocket Secure)来加密通信 。

  • 处理不支持WebSocket的客户端:使用 SockJS 作为备选方案,在不支持 WebSocket 的浏览器中模拟 WebSocket 行为 。

  • 性能与扩展

    • 对于高并发场景,考虑使用外部消息代理(如 RabbitMQ、Redis)替代简单的内存代理,以支持集群部署 。

    • 使用 @Async支持异步处理,避免阻塞消息线程 。

💎 核心对比与选择

特性

STOMP over WebSocket

原生 WebSocket API

协议层级

更高,基于帧的协议

较低,直接基于TCP

适用场景

常见的发布-订阅、点对点消息

需要精细控制、自定义协议

编程模型

类似消息控制器,更声明式

处理器接口,更命令式

前端集成

通常需STOMP客户端库(如stomp.js)

使用浏览器原生WebSocket API

会话管理

通常由框架和消息代理协助管理

需自行管理WebSocketSession

希望这份指南能帮助你顺利地在 Spring Boot 项目中集成 WebSocket!如果你在特定步骤上遇到问题,或者想了解更深入的最佳实践,比如如何结合特定的消息队列,欢迎随时提出。

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐