RSocket Interface in Spring 6 – Spring 6 中的 RSocket 接口

最后修改: 2023年 10月 3日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll explore how to utilize RSocket in the Spring Framework 6.

在本教程中,我们将探讨如何在 Spring Framework 6. 中使用RSocket

Working with RSocket has become simpler with the introduction of declarative RSocket clients in version 6 of the Spring Framework. This feature eliminates the need for repetitive boilerplate code, allowing developers to use RSocket more efficiently and effectively.

随着 Spring Framework 版本 6 中声明式 RSocket 客户端的引入,使用 RSocket 变得更加简单。该功能消除了对重复模板代码的需求,使开发人员能够更高效、更有效地使用 RSocket。

2. Maven Dependency

2.Maven 依赖性

We start by creating a Spring Boot project in our preferred IDE and add the spring-boot-starter-rsocket dependency to the pom.xml file:

首先,我们在首选的集成开发环境中创建 Spring Boot 项目,并将 spring-boot-starter-rsocket 依赖关系添加到 pom.xml 文件中:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-rsocket</artifactId>
    <version>3.1.4</version>
</dependency> 

3. Creating RSocket Server

3.创建 RSocket 服务器

First, we’ll create a responder that uses a controller to manage incoming requests:

首先,我们将创建一个应答器,使用控制器来管理传入的请求:

@MessageMapping("MyDestination")
public Mono<String> message(Mono<String> input) {
    return input.doOnNext(msg -> System.out.println("Request is:" + msg + ",Request!"))
      .map(msg -> msg + ",Response!");
}

Besides, we’ll add the following property to the application.properties file to enable the server to listen on port 7000 via MyDestination:

此外,我们还将在 application.properties 文件中添加以下属性,以启用服务器通过 MyDestination: 监听 7000 端口

spring.rsocket.server.port=7000

4. Client Code

4.客户代码

Now, we need to develop the client code. To keep things simple, we’ll create the client code in the same project but in a separate package. In reality, they must be in a unique project.

现在,我们需要开发客户端代码。为了简单起见,我们将在同一个项目中创建客户端代码,但将其放在一个单独的软件包中。实际上,它们必须放在一个单独的项目中。

To proceed, let us create the client interface:

接下来,让我们创建客户端界面:

public interface MessageClient {

    @RSocketExchange("MyDestination")
    Mono<String> sendMessage(Mono<String> input);
}

When using our client interface, we use @RSocketExchange to show the RSocket endpoint. Basically, this just means we need some info to establish the endpoint path. We can do that at the interface level by assigning a shared path. It’s super easy and helps us to know which endpoint we want to use.

在使用客户端界面时,我们使用 @RSocketExchange 来显示 RSocket 端点。基本上,这意味着我们需要一些信息来建立端点路径。我们可以通过分配共享路径在接口级实现这一点。这非常简单,而且有助于我们知道要使用哪个端点。

5. Testing

5.测试

Every Spring Boot project includes a class annotated with @SpringBootApplication. This class runs when the project is loaded. Therefore, we can use this class and add some beans to test a scenario.

每个 Spring Boot 项目都包含一个注释为 @SpringBootApplication 的类。该类在项目加载时运行。因此,我们可以使用该类并添加一些 Bean 来测试场景。

5.1. Create RSocketServiceProxyFactory Bean

5.1.创建 RSocketServiceProxyFactory Bean

First, we need to create a bean to generate an RSocketServiceProxyFactory.

首先,我们需要创建一个 Bean 来生成 RSocketServiceProxyFactory

This factory is responsible for creating proxy instances of the RSocket service interface. It handles the creation of these proxies and establishes the necessary connection to the RSocket server by specifying the host and port where the server will receive incoming connections:

该工厂负责创建 RSocket 服务接口的代理实例。它负责处理这些代理的创建,并通过指定服务器接收传入连接的主机和端口,建立与 RSocket 服务器的必要连接:

@Bean
public RSocketServiceProxyFactory getRSocketServiceProxyFactory(RSocketRequester.Builder requestBuilder) {
    RSocketRequester requester = requestBuilder.tcp("localhost", 7000);
    return RSocketServiceProxyFactory.builder(requester).build();
}

5.2. Create Message Client

5.2.创建信息客户端

Then, we’ll create a Bean responsible for generating a client interface:

然后,我们将创建一个Bean,负责生成客户端界面

@Bean
public MessageClient getClient(RSocketServiceProxyFactory factory) {
    return factory.createClient(MessageClient.class);
}

5.3. Create Runner Bean

5.3.创建运行程序 Bean

Finally, let’s create a runner bean that uses the MessageClient instance to send and receive messages from the server:

最后,让我们创建一个运行程序 Bean,使用 MessageClient 实例从服务器发送和接收消息:

@Bean
public ApplicationRunner runRequestResponseModel(MessageClient client) {
    return args -> {
        client.sendMessage(Mono.just("Request-Response test "))
          .doOnNext(message -> {
              System.out.println("Response is :" + message);
          })
          .subscribe();
    };
}

5.4. Test Results

5.4.测试结果

When we run our Spring Boot project through the command line, the following results are displayed:

当我们通过命令行运行 Spring Boot 项目时,会显示以下结果:

>>c.b.r.responder.RSocketApplication : Started 
>>RSocketApplication in 1.127 seconds (process running for 1.398)
>>Request is:Request-Response test ,Request!
>>Response is :Request-Response test ,Response!

6. RSocket Interaction Models

6.RSocket 交互模型

RSocket is a binary protocol used to create fast and responsive distributed applications. It offers different communication patterns for exchanging data between servers and clients.

RSocket 是一种二进制协议,用于创建快速响应的分布式应用程序。它为服务器和客户端之间的数据交换提供了不同的通信模式。

With these interaction models, developers can design systems that meet specific requirements for data flow, backlog, and application behavior.

有了这些交互模型,开发人员就能设计出满足数据流、积压工作和应用程序行为特定要求的系统。

RSocket has four main interaction models available. The main difference between these approaches is based on the cardinality of input and output.

RSocket 有四种主要的交互模型。这些方法之间的主要区别在于输入和输出的卡片数。

6.1. Request-Response

6.1.请求-响应

In this approach, every request receives a single response. Therefore, we used a Mono request with a cardinality of one and received a Mono response with the same cardinality.

在这种方法中,每个请求都会收到一个响应。因此,我们使用了 cardinality 为 1 的 Mono 请求,并收到了具有相同 cardinality 的 Mono 响应。

Until now, all our code in this article was based on a request-response model.

到目前为止,本文中的所有代码都是基于请求-响应模型的。

6.2. Request-Stream

6.2.请求流

When we subscribe to a newsletter, we receive a regular flow of updates from the server. When the client makes the initial request, the server sends a data stream in response.

当我们订阅时事通讯时,我们会定期收到来自服务器的更新信息流。当客户端发出初始请求时,服务器会发送一个数据流作为回应。

The request can be either a Mono or a Void, but the response will always be a Flux:

请求可以是 MonoVoid,但响应将始终是 Flux

@MessageMapping("Counter")
public Flux<String> Counter() {
    return Flux.range(1, 10)
      .map(i -> "Count is: " + i);
}

6.3. Fire-and-Forget

6.3 火–忘却

When we send a letter through the mail, we usually just drop it in the mailbox and don’t expect to receive a reply. Similarly, in the fire-and-forget context, the response can be either null or a single Mono:

当我们通过邮件寄信时,通常只是把信投进邮箱,并不指望收到回复。类似地,在 “fire-and-forget “上下文中,回复可以是 null 或单个 Mono

@MessageMapping("Warning")
public Mono<Void> Warning(Mono<String> error) {
    error.doOnNext(e -> System.out.println("warning is :" + e))
      .subscribe();
    return Mono.empty();
}

6.4. Channel

6.4.通道

Imagine a walkie-talkie that allows two-way communication where both parties can talk and listen simultaneously, just like having a conversation. This type of communication relies on sending and receiving data Flux:

想象一下,对讲机可以实现双向通信,双方可以同时进行通话和监听,就像进行对话一样。这种通信依赖于发送和接收数据Flux

@MessageMapping("channel")
public Flux<String> channel(Flux<String> input) {
    return input.doOnNext(i -> {
          System.out.println("Received message is : " + i);
      })
      .map(m -> m.toUpperCase())
      .doOnNext(r -> {
          System.out.println("RESPONSE IS :" + r);
      });
}

7. Conclusion

7.结论

In this article, we explored the new declarative RSocket client feature in Spring 6. We also learned how to use it with the @RSocketExchange annotation.

在本文中,我们探讨了 Spring 6 中新的声明式 RSocket 客户端功能。我们还学习了如何使用 @RSocketExchange 注解。

Additionally, we saw in detail how to create and set up the service proxy so that we can easily and safely connect to a remote endpoint using the TCP protocol.

此外,我们还详细了解了如何创建和设置服务代理,以便使用 TCP 协议轻松安全地连接到远程端点。

Furthermore, the source code for this tutorial is available over on GitHub.

此外,本教程的源代码可在 GitHub 上获取。