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

简介: 本文介绍了在 Spring Boot 3.3 中使用 RSocket 和 WebSocket 实现实时通信的方法。RSocket 是一种高效的网络通信协议,支持多种通信模式,适用于微服务和流式数据传输。WebSocket 则是一种标准协议,支持全双工通信,适合实时数据更新场景。文章通过一个完整的示例,展示了如何配置项目、实现前后端交互和消息传递,并提供了详细的代码示例。通过这些技术,可以大幅提升系统的响应速度和处理效率。

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

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

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

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

运行效果:

de32ed89da0e1170479598904ee9d60.png

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

本文将结合 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: 8080
spring:
  rsocket:
    server:
      port: 7000
      transport: websocket
      mapping-path: /rsocket
  websocket:
    enabled: true
    mapping: /ws
app:
  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 {
    @Autowired
    private 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 {
    @Autowired
    private AppProperties appProperties;
    @Override
    protected 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;
    }
    @Override
    public 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 则在全双工实时通信方面表现出色,适合需要即时数据更新的场景。通过本文的实例,读者可以在项目中灵活应用这两种技术,实现高效的消息交互。在前端,我们使用简单的输入框和按钮,演示了如何与服务器进行消息通信。这种方式不仅提升了用户体验,还能大幅提高系统的响应速度和处理效率。

相关文章
|
3月前
|
前端开发 Java API
Spring MVC 数据绑定机制详解:@ModelAttribute vs. @RequestParam 和 @PathVariable
本文深入解析了Spring MVC的数据绑定机制,重点对比了`@RequestParam`、`@PathVariable`和`@ModelAttribute`三种注解的使用场景与功能。`@RequestParam`适用于从查询参数或表单数据中提取简单值;`@PathVariable`用于从URL路径中获取资源标识符;而`@ModelAttribute`则能将多个请求参数自动绑定到Java对象,支持复杂数据结构的处理。通过实际案例分析,帮助开发者根据需求选择合适的注解,提升API设计与表单处理效率。
224 9
|
2月前
|
Java
SpringBoot快速搭建WebSocket服务端和客户端
由于工作需要,研究了SpringBoot搭建WebSocket双向通信的过程,其他的教程看了许多,感觉讲得太复杂,很容易弄乱,这里我只展示快速搭建过程。
213 1
|
2月前
|
网络协议 算法 物联网
Go语言的WebSocket与实时通信
本文介绍了 WebSocket 技术及其在 Go 语言中的实现。WebSocket 是一种基于 TCP 的协议,支持客户端与服务器间的持久连接和实时通信,相比传统 HTTP 更高效。文章详细讲解了 WebSocket 的核心概念、Go 语言中的相关库(如 `gorilla/websocket`),以及其实现步骤和应用场景。通过代码示例展示了如何构建 WebSocket 服务器和客户端,并探讨了其在聊天应用、实时更新、游戏和物联网等领域的实际用途。此外,还推荐了相关工具和学习资源,帮助开发者更好地掌握这一技术。
|
9月前
|
开发框架 前端开发 网络协议
Spring Boot结合Netty和WebSocket,实现后台向前端实时推送信息
【10月更文挑战第18天】 在现代互联网应用中,实时通信变得越来越重要。WebSocket作为一种在单个TCP连接上进行全双工通信的协议,为客户端和服务器之间的实时数据传输提供了一种高效的解决方案。Netty作为一个高性能、事件驱动的NIO框架,它基于Java NIO实现了异步和事件驱动的网络应用程序。Spring Boot是一个基于Spring框架的微服务开发框架,它提供了许多开箱即用的功能和简化配置的机制。本文将详细介绍如何使用Spring Boot集成Netty和WebSocket,实现后台向前端推送信息的功能。
2011 1
|
9月前
|
前端开发 JavaScript UED
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
通过在Django项目中集成Channels和WebSocket,我们能够为前后端分离的应用添加实时通信功能,实现诸如在线聊天、实时数据更新等交互式场景。这不仅增强了应用的功能性,也提升了用户体验。随着实时Web应用的日益普及,掌握Django Channels和WebSocket的集成将为开发者开启新的可能性,推动Web应用的发展迈向更高层次的实时性和交互性。
217 1
|
5月前
|
消息中间件 XML 前端开发
springBoot集成websocket实时消息推送
本文介绍了如何在Spring Boot项目中集成WebSocket实现实时消息推送。首先,通过引入`spring-boot-starter-websocket`依赖,配置`WebSocketConfig`类来启用WebSocket支持。接着,创建`WebSocketTest`服务器类,处理连接、消息收发及错误等事件,并使用`ConcurrentHashMap`管理用户连接。最后,前端通过JavaScript建立WebSocket连接,监听消息并进行相应处理。此方案适用于需要实时通信的应用场景,如聊天室、通知系统等。
288 2
|
8月前
|
缓存 监控 前端开发
Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信
本文探讨了在 Go 语言中如何集成 WebSocket 与 Socket.IO,实现高效、灵活的实时通信。首先介绍了 WebSocket 和 Socket.IO 的基本概念及其优势,接着详细讲解了 Go 语言中 WebSocket 的实现方法,以及二者集成的重要意义和具体步骤。文章还讨论了集成过程中需要注意的问题,如协议兼容性、消息格式、并发处理等,并提供了实时聊天、数据监控和在线协作工具等应用案例,最后提出了性能优化策略,包括数据压缩、缓存策略和连接管理优化。旨在帮助开发者更好地理解并应用这些技术。
372 3
|
8月前
|
缓存 监控 前端开发
在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统
本文深入探讨了在 Go 语言中实现 WebSocket 实时通信的应用,包括 WebSocket 的简介、Go 语言的优势、基本实现步骤、应用案例、注意事项及性能优化策略,旨在帮助开发者构建高效稳定的实时通信系统。
375 1
|
9月前
|
监控 小程序 前端开发
小程序全栈开发中的WebSocket实时通信实践
【10月更文挑战第3天】随着移动互联网的发展,小程序因便捷的用户体验和社交传播能力,成为企业拓展业务的新渠道。本文探讨了小程序全栈开发中的WebSocket实时通信实践,包括其实时通信、长连接及双向通信的特点,并通过实时聊天、推送、游戏和监控等功能的实现,展示了WebSocket在小程序中的应用。开发者需注意安全性、性能及兼容性等问题,以保障小程序的稳定运行和用户体验。
168 7
|
4月前
|
前端开发 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot集成Thymeleaf模板引擎——Thymeleaf 介绍
本课介绍Spring Boot集成Thymeleaf模板引擎。Thymeleaf是一款现代服务器端Java模板引擎,支持Web和独立环境,可实现自然模板开发,便于团队协作。与传统JSP不同,Thymeleaf模板可以直接在浏览器中打开,方便前端人员查看静态原型。通过在HTML标签中添加扩展属性(如`th:text`),Thymeleaf能够在服务运行时动态替换内容,展示数据库中的数据,同时兼容静态页面展示,为开发带来灵活性和便利性。
122 0