Spring websocket

本文探讨了在使用Spring WebSocket时遇到的问题及解决方案,包括代理设置导致的连接失败、DispatcherServlet配置中需要的参数调整、以及WebSocket请求无法到达Controller的方法。详细介绍了相关配置示例,旨在帮助开发者避免常见陷阱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    Spring自从4.0开始提供了对websocket的支持,配合sockjs,可以部分兼容到IE6,websocket终于可以大行其道了。

    实际使用中遇到不少问题,逐步列举出来,避免以后忘掉。

 

  1. 由于浏览器设置了http代理,结果创建websocket时失败,提示:Error in connection establishment: net::ERR_TUNNEL_CONNECTION_FAILED。取消浏览器代理后恢复正常。
  2. 在web.xml中,DispatcherServlet和spring-mvc需要用到的全部filter,都需要加上<async-supported>true</async-supported>,以便在sockjs兼容不支持websocket的浏览器时使用。
  3. 工程使用spring-mvc传统的方式配置,即使用ContextLoaderListener来加载root的Spring-contextConfigLocation(除Controller外的其他Component),使用DispatcherServlet来加载Controller。而处理websocket的业务逻辑写在Controller中,加上了@MessageMapping的注解,结果请求根本到不了Controller里面去。后来发现AbstractMethodMessageHandler负责扫描@MessageMapping,但是在该类的子类实例化时,把Spring的Root Context扔进去了,这里面是没有Controller的类的,所以后面websocket的请求就到不了Controller。将websocket的相关配置文件放到DispatcherServlet里去加载,于是问题解决。

 

相关配置示例:

web.xml:

 

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:/applicationContext*.xml</param-value>
    </context-param>

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

<servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                classpath*:/spring-*.xml
            </param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>

 applicationContext.xml:

<context:component-scan base-package="xxx.xxx">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

 spring-mvc.xml:

<context:component-scan base-package="x.x.x" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

 spring-websocket.xml:

<websocket:message-broker application-destination-prefix="/app">
        <websocket:stomp-endpoint path="/chat">
            <websocket:sockjs/>
        </websocket:stomp-endpoint>
        <websocket:simple-broker prefix="/public,/private"/>
    </websocket:message-broker>

 

 

### Spring WebSocket 使用指南 #### 1. Spring WebSocket 简介 Spring 提供了 `spring-websocket` 和 `spring-messaging` 模块来支持 WebSocket 协议,允许开发人员轻松构建实时通信的应用程序。WebSocket 是一种全双工通信协议,在单个 TCP 连接上提供了持久化的双向数据传输通道[^5]。 --- #### 2. 配置环境与依赖项 为了使用 Spring WebSocket 功能,需要引入必要的 Maven 或 Gradle 依赖项。以下是基于 Spring Boot 的典型依赖配置: ```xml <!-- Maven --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session-core</artifactId> </dependency> ``` 对于非 Spring Boot 应用,则需手动管理相关模块的版本兼容性[^4]。 --- #### 3. WebSocket 配置详解 ##### 3.1 启用消息代理模式 Spring 支持通过 STOMP (Simple Text Oriented Messaging Protocol) 来封装 WebSocket 数据流。以下是一个典型的 XML 配置示例: ```xml <websocket:message-broker application-destination-prefix="/app"> <websocket:stomp-endpoint path="/portfolio"> <websocket:sockjs/> </websocket:stomp-endpoint> <websocket:simple-broker prefix="/topic, /queue"/> </websocket:message-broker> ``` 此配置启用了 SockJS 回退机制,并设置了 `/app` 路径作为客户端发送消息的目标前缀,同时定义了简单的消息代理路径 `/topic` 和 `/queue`[^3]。 ##### 3.2 Java 注解方式配置 如果更倾向于编程式的配置方法,可以创建一个继承自 `AbstractWebSocketMessageBrokerConfigurer` 的类并覆盖相应的方法: ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic", "/queue"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").withSockJS(); } } ``` 这段代码实现了相同的逻辑,但更加灵活且易于维护[^4]。 --- #### 4. 处理器定制化 可以通过扩展 `TextWebSocketHandler` 或 `BinaryWebSocketHandler` 类来自定义处理逻辑。例如: ```java @Component public class MyWebSocketHandler extends TextWebSocketHandler { @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); System.out.println("Received Message: " + payload); // 发送响应给客户端 session.sendMessage(new TextMessage("Echo: " + payload)); } } ``` 当需要增强会话性能时,还可以利用 `ConcurrentWebSocketSessionDecorator` 对原始会话对象进行装饰[^1]。 --- #### 5. 前端实现 前端通常采用 JavaScript 结合 STOMP 客户端库完成连接建立和消息收发操作。下面展示了一个基本的例子: ```javascript var socket = new SockJS('/ws'); var stompClient = Stomp.over(socket); stompClient.connect({}, function(frame) { console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function(greeting){ alert(JSON.parse(greeting.body).content); }); }); function sendMessage() { var name = document.getElementById('name').value; stompClient.send("/app/hello", {}, JSON.stringify({'name': name})); } ``` 该脚本展示了如何订阅主题以及向服务器推送请求。 --- #### 6. 测试与调试技巧 测试 WebSocket 功能建议借助浏览器开发者工具查看网络活动详情;或者运行专门的压力测试工具如 Apache JMeter 检验系统的稳定性表现[^4]。 --- #### 7. 生产环境中常见问题及其解决方案 | **问题描述** | **可能原因分析** | **解决办法** | |--------------|------------------|-------------| | 断线频繁 | 网络波动 | 实现心跳包保持活跃状态 | | 消息丢失 | 缓冲区溢出 | 开启自动重传策略 | 更多高级特性比如集群部署下的共享存储方案可通过集成 Redis 或其他分布式缓存服务达成目标[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值