RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器

RSocket vs WebSocket:Spring Boot 3.3 中的两大实时通信利器

随着现代互联网应用的不断发展,实时通信已经成为许多应用程序不可或缺的功能。无论是社交网络、在线游戏还是数据监控系统,实时通信都能提供快速、无缝的信息交换。而实现实时通信的两种主要协议是 RSocket 和 WebSocket。

RSocket 是一种新的、先进的应用层协议,旨在提供高效的网络通信。与传统的请求/响应模式不同,RSocket 支持请求-响应、请求-流、流-流等多种模式,从而在微服务和流式数据传输中表现得更加灵活和高效。RSocket 的优势在于它可以在 TCP、WebSocket 等多种传输协议上运行,支持背压机制和多路复用,从而避免了资源的浪费,并保证了消息传递的可靠性。

WebSocket 是一种标准协议,允许客户端和服务器之间建立持久连接,客户端和服务器都可以主动发送消息。相较于传统的 HTTP 请求-响应模型,WebSocket 是全双工通信,即服务器可以实时向客户端推送数据,而不需要等待客户端发起请求,尤其适合实时数据更新场景。WebSocket 的使用场景广泛,涵盖了即时通讯、实时数据展示和多人在线游戏等。

运行效果:

若想获取项目完整代码以及其他文章的项目源码,且在代码编写时遇到问题需要咨询交流,欢迎加入下方的知识星球。

本文将结合 Spring Boot 3.3,详细讲解如何使用 RSocket 和 WebSocket 实现实时通信。我们将通过一个完整的示例,展示前后端交互、消息传递和双向通信的实际应用。文章还将结合具体的代码示例,演示如何从前端向后端发送消息,并在点击按钮时与服务器进行交互。

项目配置

项目依赖配置(pom.xml)

在 pom.xml 中引入 RSocket、WebSocket 以及其他必要的依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.3.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.icoderoad</groupId><artifactId>rsocket-websocket-demo</artifactId><version>0.0.1-SNAPSHOT</version><name>rsocket-websocket-demo</name><description>Demo project for Spring Boot</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- Spring Boot Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- RSocket 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-rsocket</artifactId></dependency><!-- WebSocket 支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><!-- Thymeleaf 模板引擎 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Lombok 支持 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

应用配置(application.yml)

server:port: 8080spring:rsocket:server:port: 7000transport: websocketmapping-path: /rsocketwebsocket:enabled: truemapping: /wsapp:rsocket-message: "这是来自 RSocket 的消息"websocket-message: "这是来自 WebSocket 的消息"

读取配置类 (RSocket 和 WebSocket 配置类)

我们使用 @ConfigurationProperties 注解读取配置文件中的 app 节点。这里使用 Lombok 来简化实体类的代码实现。

package com.icoderoad.rwebsocket.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {private String rsocketMessage;private String websocketMessage;}

RSocket 服务端实现

RSocket 提供了灵活的通信模型,允许服务端和客户端以流的方式交换数据。我们通过 @MessageMapping 来定义接收和处理客户端消息的方法。

package com.icoderoad.rwebsocket.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.stereotype.Controller;import com.icoderoad.rwebsocket.config.AppProperties;import reactor.core.publisher.Mono;@Controller
public class RSocketController {@Autowiredprivate AppProperties appProperties;@MessageMapping("rsocket.message")public Mono<String> sendMessage(String input) {return Mono.just("RSocket服务端响应: " + input + " | " + appProperties.getRsocketMessage());}
}

WebSocket 服务端实现

WebSocket 服务端使用 Spring 提供的 TextWebSocketHandler 来处理消息。我们在收到客户端消息后,通过会话对象将响应发送回客户端。

package com.icoderoad.rwebsocket.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;import com.icoderoad.rwebsocket.config.AppProperties;@Controller
public class WebSocketController extends TextWebSocketHandler {@Autowiredprivate AppProperties appProperties;@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {String clientMessage = message.getPayload();String responseMessage = "WebSocket服务端响应: " + clientMessage + " | " + appProperties.getWebsocketMessage();session.sendMessage(new TextMessage(responseMessage));}
}

WebSocket 配置类

使用 WebSocketConfigurer 来注册 WebSocket 的处理器,并允许跨域访问。

package com.icoderoad.rwebsocket.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;import com.icoderoad.rwebsocket.controller.WebSocketController;@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {private final WebSocketController webSocketController;public WebSocketConfig(WebSocketController webSocketController) {this.webSocketController = webSocketController;}@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {registry.addHandler(webSocketController, "/ws").setAllowedOrigins("*");}
}

前端实现

前端使用 Thymeleaf 渲染,并通过 jQuery 与后端的 RSocket 和 WebSocket 进行交互。用户可以输入消息,通过点击按钮发送到后端,并接收后端的响应。

在 src/main/resources/templates 目录下创建 index.html 文件:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>RSocket & WebSocket Demo</title><!-- 引入 Bootstrap 样式 --><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"><!-- 引入 jQuery 和 Bootstrap JS --><script src="https://code.jquery.com/jquery-3.6.0.min.js"></script><script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script><!-- 引入 RSocket 库 --><script src="/js/rsocket-core.min.js"></script><script src="/js/rsocket-websocket-client.min.js"></script><style>.message-box {max-height: 300px;overflow-y: auto;border: 1px solid #dee2e6;padding: 10px;border-radius: 0.25rem;background-color: #f8f9fa;}.message-box p {margin-bottom: 0.5rem;}</style>
</head>
<body><div class="container"><h1 class="mt-5">RSocket & WebSocket Demo</h1><!-- WebSocket 区域 --><div class="mt-5"><h3>WebSocket 消息</h3><div class="input-group mb-3"><input type="text" id="websocket-input" class="form-control" placeholder="输入 WebSocket 消息"><button id="send-websocket" class="btn btn-primary">发送 WebSocket 消息</button></div><div id="websocket-messages" class="message-box"></div></div><!-- RSocket 区域 --><div class="mt-5"><h3>RSocket 消息</h3><div class="input-group mb-3"><input type="text" id="rsocket-input" class="form-control" placeholder="输入 RSocket 消息"><button id="send-rsocket" class="btn btn-success">发送 RSocket 消息</button></div><div id="rsocket-messages" class="message-box"></div></div></div><script>$(document).ready(function () {// WebSocket 连接const ws = new WebSocket("ws://localhost:8080/ws");ws.onmessage = function (event) {$("#websocket-messages").append(`<p>${event.data}</p>`);};// 发送 WebSocket 消息$("#send-websocket").click(function () {const message = $("#websocket-input").val();if (message.trim()) {ws.send(message);$("#websocket-input").val('');}});const { RSocketClient } = window['rsocket-core'];const { default: RSocketWebSocketClient } = window['rsocket-websocket-client'];// RSocket 客户端创建和连接async function createRSocketClient() {const transportOptions = {url: 'ws://localhost:7001/rsocket',};const setupOptions = {keepAlive: 60000,lifetime: 180000,dataMimeType: 'application/json',metadataMimeType: 'message/x.rsocket.routing.v0',};const transport = new RSocketWebSocketClient(transportOptions);const client = new RSocketClient({setup: setupOptions,transport});try {return await client.connect();} catch (error) {console.error("RSocket 连接错误: ", error);throw error;}}// 处理 RSocket 消息async function setupRSocket() {try {const socket = await createRSocketClient();$("#send-rsocket").click(function () {const message = $("#rsocket-input").val();if (message.trim()) {socket.requestResponse({data: message,metadata: String.fromCharCode('rsocket.message'.length) + 'rsocket.message'}).subscribe({onComplete: (response) => {$("#rsocket-messages").append(`<p>${response.data}</p>`);$("#rsocket-input").val('');},onError: (error) => {console.error("RSocket 错误: ", error);}});}});} catch (error) {console.error("启动 RSocket 客户端失败: ", error);}}setupRSocket();});</script>
</body>
</html>

总结

通过结合 RSocket 和 WebSocket,我们可以在 Spring Boot 3.3 中轻松实现高效的实时通信。RSocket 通过其多种通信模型和背压机制,为流式数据传输提供了强大的支持;WebSocket 则在全双工实时通信方面表现出色,适合需要即时数据更新的场景。通过本文的实例,读者可以在项目中灵活应用这两种技术,实现高效的消息交互。在前端,我们使用简单的输入框和按钮,演示了如何与服务器进行消息通信。这种方式不仅提升了用户体验,还能大幅提高系统的响应速度和处理效率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/57611.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高精度KEITHLEY2636A参数资料吉时利2636B数字源表

Keithley 2636A吉时利2636B数字源表&#xff0c;200V&#xff0c;1fA/1uV&#xff0c;2 通道&#xff0c;10A 脉冲 Keithley 2636A SourceMeter 是 Keithley 最新 IV 源测量仪器的一部分&#xff0c;可用作台式 IV 表征工具或多通道 IV 测试系统的构建块组件。对于台式使用&am…

STM32通信协议-I2C

目录 一&#xff0c;IC2的协议规则 I2C总线是PHILIPS公司开发的两线式串行总线&#xff0c;I2C总线主要解决了单片机一对多通信的问题 两根通信线&#xff1a;SCL,SDA&#xff0c;同步&#xff0c;半双工通信&#xff0c;支持数据应答机制&#xff0c;支持总线挂载多设备。 …

策略模式是一种行为设计模式

策略模式是一种行为设计模式&#xff0c;允许你定义一系列算法、封装每一个算法&#xff0c;并使它们可以相互替换。 策略模式使得算法的变化独立于使用算法的客户端。以下是一个用策略模式实现不同类型促销活动的 Java 示例。 步骤 定义促销策略接口&#xff1a;创建一个接…

Python异常检测- 单类支持向量机(One-Class SVM)

系列文章目录 Python异常检测- Isolation Forest&#xff08;孤立森林&#xff09; python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子&#xff08;LOF&#xff09;算法 Python异常检测- DBSCAN 文章目录 系列文章目录前言一、On…

图像高清化(论文复现)

图像高清化(论文复现) 本文所涉及所有资源均在传知代码平台可获取 文章目录 图像高清化(论文复现)概述算法原理核心逻辑效果演示使用方式概述 本文复现论文 “Zero-Shot” Super-Resolution using Deep Internal Learning[1] 提出的图像超分辨率方法。 图像超分辨率是指从低…

如何从模块内部运行 Pytest

在 Python 中&#xff0c;pytest 是一个强大的测试框架&#xff0c;用于编写和运行测试用例。通常我们会在命令行中运行 pytest&#xff0c;但是有时你可能希望从模块或脚本的内部运行 pytest&#xff0c;比如为了自动化测试或集成到某个工作流程中。 1、问题背景 当你从模块…

计算机视觉中的坐标变换

1.概述 高级驾驶辅助系统&#xff08;ADAS&#xff09;领域&#xff0c;存在多种常用的坐标系&#xff1a;LiDAR 坐标系、车辆坐标系、相机坐标系、图像坐标系等。因为和这些坐标系频繁打交道&#xff0c;本文对点的旋转与坐标系旋转等变换给出直观推导与说明。 2.坐标点平移…

Android Audio基础——音频混音结束处理(十一)

上一篇文章主要介绍了混音线程 MixerThread 的创建及混音流程的处理过程,这里我们看一下完成混音后的调用流程。 一、音频处理结束 在音频处理中,结束阶段通常分为两个主要阶段:sleep 和 standby。这两个阶段的目的是为了节省资源和优化性能。 源码位置:/frameworks/av/s…

06 go语言(golang) - 循环语句运算符

循环语句 在Go语言中&#xff0c;for 循环是实现循环的主要方式&#xff0c;它非常灵活且强大。 1. 基本的 for 循环 这种形式类似于 C/C 和 Java 中的 for 循环。它包括三个部分&#xff1a;初始化语句&#xff1b;条件表达式&#xff1b;后续操作&#xff08;通常是递增或…

多租户架构的全景分析(基本概念、实现策略、资源管理和隔离、数据安全与隔离、性能优化、扩展性与升级、案例研究)

文章目录 1. 多租户的基本概念2. 多租户的实现策略2.1 独立数据库模式2.2 共享数据库-独立Schema模式2.3 共享数据库-共享Schema模式 3. 资源管理和隔离4. 数据安全与隔离5. 性能优化6. 扩展性与升级7. 案例研究总结 多租户架构在云计算和SaaS应用中越来越流行&#xff0c;因为…

Netty无锁化设计之对象池实现

池化技术是比较常见的一种技术&#xff0c;在平时我们已经就接触很多了&#xff0c;比如线程池&#xff0c;数据库连接池等等。当我们要使用一个资源的时候从池中去获取&#xff0c;用完就放回池中以便其他线程可以使用&#xff0c;这样的目的就是为了减少资源开销&#xff0c;…

【编程语言】C++ 中 vector 初始化的多种方法详解

在 C 中&#xff0c;vector 是一个非常重要的数据结构&#xff0c;它提供了动态数组的功能&#xff0c;可以在运行时根据需要自动调整大小。vector 的初始化方法有多种&#xff0c;既可以简单地进行初始化&#xff0c;也可以根据特定的需求进行复杂的初始化。在这篇博客中&…

JMeter 动态参数赋值实践

目录 前言 单线程 用户参数 场景说明 实战结果 配置明细 单线程 CSV Data Set Config 场景说明 实践结果 配置明细 多线程循环单次执行 场景说明 实践结果 配置明细 单线程 控制器 用户自定义变量 用户参数 场景说明 实战结果 配置明细 多并发 多接口 …

AudioSegment 提高音频音量 - python 实现

一些采集的音频声音音量过小可以通过 AudioSegment 实现音量增强。 按照 python 库&#xff1a; pip install AudioSegment 代码具体实现&#xff1a; #-*-coding:utf-8-*- # date:2024-10 # Author: DataBall - XIAN # Function: 音频增加音量import os from pydub import …

Matlab学习01-矩阵

目录 一&#xff0c;矩阵的创建 1&#xff0c;直接输入法创建矩阵 2&#xff0c;利用M文件创建矩阵 3&#xff0c;利用其它文本编辑器创建矩阵 二&#xff0c;矩阵的拼接 1&#xff0c;基本拼接 1&#xff09; 水平方向的拼接 2&#xff09;垂直方向的拼接 3&#xf…

记录:网鼎杯2024赛前热身WEB01

目录扫描&#xff0c;发现上传点&#xff0c;判断可能存在文件上传漏洞&#xff0c;并根据文件后缀判断网站开发语言为php 编写蚁剑一句话木马直接上传 蚁剑连接 这里生成 的flag是随机的&#xff0c;因为烽火台反作弊会随机生成环境&#xff0c;在一顿查找后&#xff0c;在hom…

今日总结10.23

什么是反射 优缺点是什么 一、光学中的反射 定义&#xff1a; 反射是光线在与物体表面相遇时&#xff0c;由于介质的折射率不同而产生的一种现象。当光线照射到一个物体表面时&#xff0c;一部分光线会被反射回来&#xff0c;这个过程被称为反射。 优点&#xff1a; 1.反射…

stm32F103 实现呼吸灯效果

目录 硬件连接 软件实现步骤 初始化系统时钟。 配置 GPIO 引脚。 配置定时器以生成 PWM 信号。 在主循环中调整 PWM 占空比以实现呼吸效果。 示例代码 1. 初始化系统时钟 2. 配置 GPIO 引脚 3. 配置定时器以生成 PWM 信号 4. 在主循环中调整 PWM 占空比以实现呼吸效…

5G RedCap工业路由器赋能电力物联网应用

随着5G轻量化技术应用的推进&#xff0c;5G RedCap旨在提供低功耗、低成本、广覆盖等功能特点赋能电力智能化升级。特别适用于工业物联网、低空经济、车联网、消费电子和轻量级5G的需求。 5G RedCap工业路由器的特点 低功耗&#xff1a;5G RedCap工业路由器通过节能技术&#…

npm run serve 提示异常Cannot read property ‘upgrade‘ of undefined

npm run serve 提示Cannot read property ‘upgrade’ of undefined 一般是proxy的target代理域名问题导致的&#xff0c;如下&#xff1a; 解决方案&#xff1a; proxy: { “/remoteDealerReportApi”: { target: ‘http://demo-.com.cn’, //此域名有问题&#xff0c;会导致…