温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

spring boot 中如何使用Websocket

发布时间:2021-07-30 13:52:05 来源:亿速云 阅读:193 作者:Leah 栏目:大数据
# Spring Boot 中如何使用WebSocket ## 1. WebSocket 简介 ### 1.1 什么是WebSocket WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务端主动向客户端推送数据。与传统的HTTP请求-响应模式不同,WebSocket提供了持久化的连接,使得客户端和服务器之间的数据交换变得更加高效。 ### 1.2 WebSocket与HTTP的区别 | 特性 | WebSocket | HTTP | |---------------|-------------------------------|--------------------------| | 通信模式 | 全双工 | 半双工(请求-响应) | | 连接持续时间 | 持久化 | 短暂(每次请求后关闭) | | 头部开销 | 初始握手后基本无头部 | 每次请求都携带完整头部 | | 适用场景 | 实时应用(聊天、游戏等) | 传统网页内容获取 | ### 1.3 WebSocket的应用场景 - 实时聊天应用 - 在线协作编辑工具 - 多人在线游戏 - 股票行情实时推送 - IoT设备状态监控 ## 2. Spring Boot集成WebSocket ### 2.1 添加依赖 在`pom.xml`中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> 

2.2 配置WebSocket

创建配置类启用WebSocket支持:

@Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(myHandler(), "/ws") .setAllowedOrigins("*"); } @Bean public WebSocketHandler myHandler() { return new MyWebSocketHandler(); } } 

2.3 实现WebSocket处理器

创建自定义处理器处理消息:

public class MyWebSocketHandler extends TextWebSocketHandler { private static final List<WebSocketSession> sessions = new CopyOnWriteArrayList<>(); @Override public void afterConnectionEstablished(WebSocketSession session) { sessions.add(session); System.out.println("New connection: " + session.getId()); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) { String payload = message.getPayload(); System.out.println("Received: " + payload); // 广播消息给所有客户端 for (WebSocketSession s : sessions) { try { s.sendMessage(new TextMessage("Echo: " + payload)); } catch (IOException e) { e.printStackTrace(); } } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) { sessions.remove(session); System.out.println("Connection closed: " + session.getId()); } } 

3. 高级配置与功能

3.1 STOMP协议支持

添加STOMP子协议支持:

@Configuration @EnableWebSocketMessageBroker public class WebSocketStompConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws-stomp") .setAllowedOrigins("*") .withSockJS(); } } 

3.2 使用SockJS实现降级兼容

当浏览器不支持WebSocket时,SockJS会自动降级使用其他技术:

registry.addEndpoint("/ws") .withSockJS(); 

3.3 消息拦截器

实现握手拦截器:

public class AuthHandshakeInterceptor implements HandshakeInterceptor { @Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) { // 验证逻辑 return true; // 返回false拒绝连接 } @Override public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) { } } 

注册拦截器:

registry.addHandler(myHandler(), "/ws") .addInterceptors(new AuthHandshakeInterceptor()); 

4. 客户端实现

4.1 JavaScript客户端

const socket = new WebSocket('ws://localhost:8080/ws'); socket.onopen = () => { console.log('Connected'); socket.send('Hello Server!'); }; socket.onmessage = (event) => { console.log('Received: ' + event.data); }; socket.onclose = () => { console.log('Disconnected'); }; 

4.2 Java客户端

使用WebSocketClient

WebSocketClient client = new StandardWebSocketClient(); WebSocketSession session = client.doHandshake( new WebSocketHandler() { /*...*/ }, "ws://localhost:8080/ws" ).get(); 

5. 性能优化与安全

5.1 性能调优

  • 设置消息缓冲区大小:
     registry.setMessageSizeLimit(128 * 1024); // 128KB 
  • 使用二进制消息替代文本消息减少体积
  • 实现心跳机制保持连接

5.2 安全措施

  • 启用CSRF防护
  • 限制消息频率防止DoS攻击
  • 实现身份验证
  • 使用WSS(WebSocket Secure)

6. 常见问题与解决方案

6.1 连接失败排查

  1. 检查服务端是否启动
  2. 验证端点路径是否正确
  3. 检查跨域配置
  4. 查看服务器日志

6.2 消息丢失处理

  • 实现消息确认机制
  • 添加重试逻辑
  • 使用持久化消息队列

6.3 集群环境下的挑战

解决方案: - 使用Redis广播消息

 @Configuration @EnableRedisRepositories public class RedisConfig { @Bean public RedisMessageListenerContainer redisContainer(RedisConnectionFactory factory) { RedisMessageListenerContainer container = new RedisMessageListenerContainer(); container.setConnectionFactory(factory); return container; } } 
  • 采用专业的消息中间件如RabbitMQ

7. 实战案例:构建聊天室

7.1 服务端实现

@Controller public class ChatController { @MessageMapping("/chat.send") @SendTo("/topic/public") public ChatMessage sendMessage(@Payload ChatMessage message) { return message; } @MessageMapping("/chat.join") @SendTo("/topic/public") public ChatMessage join(@Payload ChatMessage message, SimpMessageHeaderAccessor headerAccessor) { headerAccessor.getSessionAttributes().put("username", message.getSender()); return message; } } 

7.2 前端页面

<div id="chat"> <input type="text" id="message" /> <button onclick="send()">Send</button> <div id="messages"></div> </div> <script> const stompClient = new StompJs.Client({ brokerURL: 'ws://localhost:8080/ws-stomp' }); stompClient.onConnect = () => { stompClient.subscribe('/topic/public', (message) => { showMessage(JSON.parse(message.body)); }); }; function send() { const message = document.getElementById('message').value; stompClient.publish({ destination: '/app/chat.send', body: JSON.stringify({'content': message}) }); } </script> 

8. 测试与监控

8.1 单元测试

@SpringBootTest class WebSocketTests { @Autowired private WebSocketHandler handler; @Test void testMessageHandling() throws Exception { TestWebSocketSession session = new TestWebSocketSession(); handler.afterConnectionEstablished(session); TextMessage message = new TextMessage("test"); handler.handleMessage(session, message); assertEquals(1, session.getSentMessages().size()); } } 

8.2 监控指标

暴露WebSocket统计信息:

@Bean public WebSocketMetrics webSocketMetrics() { return new WebSocketMetrics(); } 

9. 总结与最佳实践

9.1 核心要点总结

  • WebSocket实现了真正的全双工通信
  • Spring Boot通过spring-boot-starter-websocket简化集成
  • STOMP协议提供了更高级的消息模式
  • SockJS保证了兼容性

9.2 推荐实践

  1. 为生产环境始终使用WSS
  2. 实现合理的心跳机制
  3. 限制单个连接的消息频率
  4. 使用DTO对象而非原始字符串
  5. 考虑实现消息持久化

9.3 扩展学习方向

  • 研究RSocket协议
  • 学习WebRTC技术
  • 探索gRPC的双向流
  • 了解Quarkus的响应式WebSocket实现

附录:完整配置示例

@Configuration @EnableWebSocketMessageBroker public class FullWebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableStompBrokerRelay("/topic", "/queue") .setRelayHost("rabbitmq-host") .setRelayPort(61613); registry.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws-full") .setHandshakeHandler(new CustomHandshakeHandler()) .addInterceptors(new AuthInterceptor()) .setAllowedOrigins("*") .withSockJS(); } @Override public void configureWebSocketTransport(WebSocketTransportRegistration registry) { registry.setMessageSizeLimit(512 * 1024) .setSendTimeLimit(10000) .setSendBufferSizeLimit(1024 * 1024); } } 

”`

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI