Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >SpringBoot3-整合WebSocket

SpringBoot3-整合WebSocket

作者头像
CoderJia
发布于 2024-12-16 04:34:56
发布于 2024-12-16 04:34:56
40000
代码可运行
举报
运行总次数:0
代码可运行

1. 什么是WebSocket?

WebSocket 是一种网络通信协议,提供全双工通信通道,使服务器可以主动向客户端推送数据。与传统的 HTTP 请求-响应模式不同,WebSocket 在建立连接后,允许服务器和客户端之间进行双向实时通信。

主要特点:

  • 建立在 TCP 协议之上
  • 与 HTTP 协议有良好的兼容性
  • 数据格式轻量,性能开销小
  • 可以发送文本和二进制数据
  • 没有同源限制,客户端可以与任意服务器通信

2. 环境准备

2.1 项目依赖

首先在pom.xml中添加必要的依赖:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.5</version>
</parent>

<dependencies>
    <!-- WebSocket依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    
    <!-- Web依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Lombok依赖(可选) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
image-20241215200948577
image-20241215200948577

3. WebSocket配置

3.1 WebSocket配置类

创建 WebSocket 配置类,启用 WebSocket 功能并注册端点:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.coderjia.boot3websocket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 * @author CoderJia
 * @create 2024/12/15 下午 08:11
 * @Description
 **/
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler(), "/websocket")
                .setAllowedOrigins("*"); // 允许跨域访问
    }

    @Bean
    public WebSocketHandler webSocketHandler() {
        // 使用自定义的WebSocket处理器
        return new CustomWebSocketHandler();
    }
}

3.2 自定义WebSocket处理器

创建自定义的 WebSocket 处理器,处理消息收发:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.coderjia.boot3websocket.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author CoderJia
 * @create 2024/12/15 下午 08:21
 * @Description
 **/
@Component
@Slf4j
public class CustomWebSocketHandler extends TextWebSocketHandler {

    // 用于存储WebSocket会话
    private final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String sessionId = session.getId();
        sessions.put(sessionId, session);
        log.info("WebSocket连接建立成功:{}", sessionId);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        log.info("收到消息:{}", payload);

        // 发送回复消息
        String replyMessage = "服务器收到消息:" + payload;
        session.sendMessage(new TextMessage(replyMessage));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String sessionId = session.getId();
        sessions.remove(sessionId);
        log.info("WebSocket连接关闭:{}", sessionId);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.error("WebSocket传输错误", exception);
    }

    // 广播消息给所有连接的客户端
    public void broadcastMessage(String message) {
        sessions.values().forEach(session -> {
            try {
                session.sendMessage(new TextMessage(message));
            } catch (IOException e) {
                log.error("广播消息失败", e);
            }
        });
    }
}

4. 控制器

创建 REST 控制器,用于测试消息广播:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@RestController
@RequestMapping("/api/websocket")
public class WebSocketController {
    
    private final CustomWebSocketHandler webSocketHandler;
    
    public WebSocketController(CustomWebSocketHandler webSocketHandler) {
        this.webSocketHandler = webSocketHandler;
    }
    
    @PostMapping("/broadcast")
    public ResponseEntity<String> broadcastMessage(@RequestBody String message) {
        webSocketHandler.broadcastMessage(message);
        return ResponseEntity.ok("消息广播成功");
    }
}

5. 前端实现

5.1 HTML页面

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <title>WebSocket测试</title>
</head>
<body>
    <div>
        <h2>WebSocket测试页面</h2>
        <div>
            <input type="text" id="messageInput" placeholder="输入消息">
            <button onclick="sendMessage()">发送</button>
        </div>
        <div id="messages" style="margin-top: 20px;"></div>
    </div>
    
    <script>
        let ws = null;
        
        function connect() {
            ws = new WebSocket('ws://localhost:8080/websocket');
            
            ws.onopen = function() {
                console.log('WebSocket连接已建立');
                appendMessage('系统消息:连接已建立');
            };
            
            ws.onmessage = function(event) {
                appendMessage('收到消息:' + event.data);
            };
            
            ws.onclose = function() {
                console.log('WebSocket连接已关闭');
                appendMessage('系统消息:连接已关闭');
            };
            
            ws.onerror = function(error) {
                console.error('WebSocket错误:', error);
                appendMessage('系统消息:连接发生错误');
            };
        }
        
        function sendMessage() {
            const messageInput = document.getElementById('messageInput');
            const message = messageInput.value;
            
            if (ws && message) {
                ws.send(message);
                appendMessage('发送消息:' + message);
                messageInput.value = '';
            }
        }
        
        function appendMessage(message) {
            const messagesDiv = document.getElementById('messages');
            const messageElement = document.createElement('div');
            messageElement.textContent = message;
            messagesDiv.appendChild(messageElement);
        }
        
        // 页面加载完成后连接WebSocket
        window.onload = connect;
    </script>
</body>
</html>

6. 测试WebSocket功能

  1. 启动 SpringBoot 应用
  2. 打开多个浏览器窗口访问 HTML 页面
  3. 在任意窗口发送消息,观察其他窗口是否收到消息
  4. 使用 POST 请求测试广播功能:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
curl -X POST http://localhost:8080/api/websocket/broadcast \
     -H "Content-Type: text/plain" \
     -d "这是一条广播消息"
连接
连接
HTML页面
HTML页面
测接口
测接口
广播
广播

7. 进阶功能

7.1 心跳检测

为了保持WebSocket连接的稳定性,可以实现心跳机制:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @Scheduled(fixedRate = 10000) // 每10秒发送一次心跳,需要启动类或配置类上添加@EnableScheduling
    public void sendHeartbeat() {
        String heartbeat = "heartbeat";
        sessions.values().forEach(session -> {
            try {
                session.sendMessage(new TextMessage(heartbeat));
            } catch (IOException e) {
                log.error("发送心跳消息失败", e);
            }
        });
    }
心跳
心跳

7.2 消息重试机制

当消息发送失败时,实现重试机制:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void sendMessageWithRetry(WebSocketSession session, String message, int maxRetries) {
    int retryCount = 0;
    while (retryCount < maxRetries) {
        try {
            session.sendMessage(new TextMessage(message));
            return;
        } catch (IOException e) {
            retryCount++;
            log.error("消息发送失败,尝试重试 {}/{}", retryCount, maxRetries);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ie) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }
    log.error("消息发送失败,达到最大重试次数");
}

8. 注意事项

  1. 连接管理
    • 及时清理断开的连接
    • 实现最大连接数限制
    • 考虑使用连接池管理WebSocket连接
  2. 安全性
    • 实现用户认证
    • 添加消息加密
    • 设置适当的跨域策略
  3. 性能优化
    • 使用消息队列处理大量消息
    • 实现消息压缩
    • 控制消息大小
  4. 错误处理
    • 完善异常处理机制
    • 实现日志记录
    • 添加监控告警

9. 总结

SpringBoot 3 整合 WebSocket 提供了一种高效的实时通信解决方案。通过本文的配置和示例,你可以快速实现:

  • WebSocket服务器端配置
  • 客户端连接管理
  • 消息收发处理
  • 广播功能
  • 心跳检测
  • 错误处理

这些功能可以作为构建实时应用的基础,如在线聊天、实时数据推送、游戏等场景。根据具体需求,你可以在此基础上扩展更多功能。

参考资料

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
通过DaemonSet-CRD方式采集TKE日志
在TKE中LogListener是以DaemonSet模式运行,可通过CRD方式创建采集配置采集TKE集群日志。本文介绍如何通过CRD方式创建采集配置。
tinkerli
2021/04/07
1.2K1
通过DaemonSet-CRD方式采集TKE日志
【最佳实践&原理解析】K8S日志一键采集,快速分析
随着云计算技术的发展,越来越多的公司开始向业务更敏捷、成本更低、可伸缩、更灵活的云原生架构转变。而在云原生技术栈中,容器已经成为应用分发和交付的标准技术,将应用与底层运行环境进行解耦;其中 Kubernetes 已经成为容器编排的事实标准,被广泛用于自动部署、扩展和管理容器化应用。
日志服务CLS小助手
2022/08/02
2.1K5
TKE容器服务结合日志服务进行使用详解
日志采集功能是容器服务为用户提供的集群内日志采集工具,可以将集群内服务或集群节点特定路径文件的日志发送至 Kafka、Elasticsearch 或者 腾讯云日志服务(CLS)。日志采集功能适用于需要对 Kubernetes 集群内服务日志进行存储和分析的用户。
pengsiryan
2019/12/21
1.1K0
TKE集群日志解决方案之日志采集
当前技术领域容器盛行,已然是一个云原生的时代, 在技术领域都或多或少跟云计算、容器、Kubernetes、云原生应用有着不同的渊源。云原生的技术变更带来了革命性的变化, 节省了成本,使得系统能够快速应对业务的快速迭代发布, 从而推动业务的快速发展。但同时导致了公司对于上云后对于应用的监控,管理发生了很大的变化.
朱瑞卿
2020/08/23
2.1K2
TKE集群日志解决方案之日志采集
日志源解析|K8s 集群部署 CLS 日志服务原理及场景实现
kahing,腾讯云CLS产品经理,负责CLS云原生日志的云产品接入工作。 willyi,腾讯云高级开发工程师,负责CLS云原生日志服务云原生生态建设,致力于大规模云原生设施的落地和实践工作。 简介 日志服务 (Cloud Log Service, CLS)支持采集自建K8s集群上的日志,在进行日志采集前,需要在K8s自建集群上通过CRD定义日志采集配置(LogConfig),并部署安装Log-Provisoner,Log-Agent,以及LogListener。针对使用腾讯云容器服务(Tencent
腾讯云原生
2021/10/25
1.1K0
k8s 日志采集最佳实践
通常一个线上问题的定位流程是: 通过 Metric 发现问题, 根据 Trace 定位到问题模块,根据模块具体的日志定位问题原因。在日志中包括了错误、关键变量、代码运行路径等信息,这些是问题排查的核心,因此日志永远是线上问题排查的必经路径;
iginkgo18
2021/11/09
2.6K0
kubernetes中日志采集
在Kubernetes中,每个容器都有自己的标准输出和标准错误输出,我们可以使用容器运行时提供的工具来采集这些输出,并将其重定向到日志文件中。例如,我们可以使用Docker提供的“docker logs”命令来查看容器的日志输出:
堕落飞鸟
2023/03/29
1K0
网易基于Filebeat的日志采集服务设计与实践
云原生技术大潮已经来临,技术变革迫在眉睫。 在这股技术潮流之中,网易推出了 轻舟微服务平台,集成了微服务、Service Mesh、容器云、DevOps等组件,已经广泛应用于公司内部,同时也支撑了很多外部客户的云原生化改造和迁移。
Spark学习技巧
2021/02/12
1.7K2
网易基于Filebeat的日志采集服务设计与实践
TKE操作笔记04
良好的监控环境为腾讯云容器服务高可靠性、高可用性和高性能提供重要保证。您可以方便为不同资源收集不同维度的监控数据,能方便掌握资源的使用状况,轻松定位故障。 腾讯云容器服务提供集群、节点、工作负载、Pod、Container 5个层面的监控数据收集和展示功能。 收集监控数据有助于您建立容器集群性能的正常标准。通过在不同时间、不同负载条件下测量容集群的性能并收集历史监控数据,您可以较为清楚的了解容器集群和服务运行时的正常性能,并能快速根据当前监控数据判断服务运行时是否处于异常状态,及时找出解决问题的方法。例如,您可以监控服务的 CPU 利用率、内存使用率和磁盘 I/O
聂伟星
2020/06/05
7960
Logging Operator - 优雅的云原生日志管理方案 (三)
Logging Operator是BanzaiCloud下开源的一个云原生场景下的日志采集方案。它在 2020 年 3 月的时候经过重构后的 v3 版本,底层凭借高效的 fluentbit 和插件丰富的 flunetd,Logging Operator几乎已经完美的适配了 kubernetes 模式下的日志采集场景,未来可期。去年偶然间发现Rancher 在 2.5 版本之后也采用了 Logging Operator 作为统一的日志解决方案,足以说明它正在被一些以 Kubernetes 为核心的管理平台接受,并集成至内部(也包括小白的 KubeGems)。
云原生小白
2022/01/11
1K0
腾讯云TKE-日志案例: 基于fluentbit、elasticsearch、kibana日志解决方案
本文介绍利用在腾讯云TKE应用市场中的三款软件 fluentbit,elasticsearch和kibana搭建一套适用于kubernetes环境的云原生一站式日志解决方案。
朱瑞卿
2020/11/02
2.1K0
腾讯云TKE-日志案例: 基于fluentbit、elasticsearch、kibana日志解决方案
k8s01# K8s日志采集与服务质量QoS
应用容器化后的日志采集该选择何种方式?该如何权衡?不同的服务质量QoS对Node的稳定性影响是怎么样的,本文就捋一捋这个。主要内容有:
瓜农老梁
2022/12/03
5250
k8s01# K8s日志采集与服务质量QoS
kube-apiserver审计日志记录和采集
Kubernetes 审计功能提供了与安全相关的按时间顺序排列的记录集,记录单个用户、管理员或系统其他组件影响系统的活动顺序。它能帮助集群管理员处理以下问题:
我的小碗汤
2019/01/23
3.5K0
kube-apiserver审计日志记录和采集
使用log-Pilot做日志收集
log-Pilot是一个智能容器日志采集工具,它不仅能够高效便捷地将容器日志采集输出到多种存储日志后端,同时还能够动态地发现和采集容器内部的日志文件,更多咨询可以移步这里。
极客运维圈
2020/07/01
2.7K0
使用fluent bit+ClickHouse 实现K8s日志采集
Fluent bit是一个用C写成的插件式、轻量级、多平台开源日志收集工具。它允许从不同的源收集数据并发送到多个目的地。完全兼容docker和kubernetes生态环境。
灵雀云
2021/12/28
2.8K0
使用fluent bit+ClickHouse 实现K8s日志采集
云原生系统日志采集详解
谈到日志收集,估计大家第一个想到的就是ELK这个比较成熟的方案,如果是特别针对云原生上的,那么将采集器稍微变一下为
大发明家
2021/12/17
1.2K0
使用filebeat采集TKE容器日志
当业务使用腾讯云容器服务TKE进行部署时,可以通过filebeat来采集TKE中各个pod的日志,写入到下游的Elasticsearch集群中,然后在kibana上进行日志的查询与分析。本文介绍如何使用filebeat daemonset的方式采集容器中的日志。
bellen
2021/07/21
2.9K1
使用filebeat采集TKE容器日志
Kubernetes集群监控-使用ELK实现日志监控和分析
日志对于调试问题和监视集群情况也是非常有用的。而且大部分的应用都会有日志记录,对于传统的应用大部分都会写入到本地的日志文件之中。对于容器化应用程序来说则更简单,只需要将日志信息写入到 stdout 和 stderr 即可,容器默认情况下就会把这些日志输出到宿主机上的一个 JSON 文件之中,同样也可以通过 docker logs 或者 kubectl logs 来查看到对应的日志信息。
王先森sec
2023/11/20
1K0
Kubernetes集群监控-使用ELK实现日志监控和分析
Kubernetes中部署ELK Stack日志收集平台
ELK是Elasticsearch、Logstash、Kibana三大开源框架首字母大写简称。市面上也被称为Elastic Stack。其中Elasticsearch是一个基于Lucene、分布式、通过Restful方式进行交互的近实时搜索平台框架。像类似百度、谷歌这种大数据全文搜索引擎的场景都可以使用Elasticsearch作为底层支持框架,可见Elasticsearch提供的搜索能力确实强大,市面上很多时候我们简称Elasticsearch为es。Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集的不同格式数据,经过过滤后支持输出到不同目的地(文件/MQ/redis/elasticsearch/kafka等)。Kibana可以将elasticsearch的数据通过友好的页面展示出来,提供实时分析的功能。
没有故事的陈师傅
2021/07/21
1.8K6
【玩转腾讯云】记一次容器服务日志处理过程
在目前小程序为主的大背景下,有客户大部分业务在腾讯云,使用的大部分为容器服务,在大规模的使用容器下,需要对容器内业务的日志采集及分析,在腾讯云对应容器服务的日志提供了两种消费方式:Kafka、日志服务CLS。
KaliArch
2021/04/23
8180
【玩转腾讯云】记一次容器服务日志处理过程
推荐阅读
相关推荐
通过DaemonSet-CRD方式采集TKE日志
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验