1. 概述

在这个教程中,我们将探讨如何在Spring框架6中利用RSocket。自Spring框架6版本引入声明式RSocket客户端以来,与RSocket的交互变得更加简单。这一特性消除了重复的样板代码,使开发者能够更高效地使用RSocket。

2. Maven依赖

首先,在我们首选的IDE中创建一个Spring Boot项目,并在pom.xml文件中添加spring-boot-starter-rsocket依赖:

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

3. 创建RSocket服务器

首先,我们将创建一个响应者,使用控制器管理接收的请求:

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

此外,我们需要在application.properties文件中添加一个属性,让服务器通过MyDestination监听端口7000:

spring.rsocket.server.port=7000

4. 客户端代码

现在,我们需要编写客户端代码。为了简化,我们将在同一个项目但不同的包中创建客户端代码。在实际应用中,它们应该位于独立的项目中。

接下来,我们创建客户端接口:

public interface MessageClient {

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

当我们使用客户端接口时,使用@RSocketExchange显示RSocket端点。基本上,这意味着我们需要提供一些信息来确定端点路径。我们可以在接口级别分配一个共享路径,这非常简单,有助于我们知道要使用的端点。

5. 测试

每个Spring Boot项目都包含一个带有@SpringBootApplication注解的类。当项目加载时,这个类会运行。因此,我们可以使用这个类并添加一些bean来测试场景。

5.1. 创建RSocketServiceProxyFactory Bean

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

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

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

5.2. 创建消息客户端

然后,我们将创建一个负责生成客户端接口的Bean

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

5.3. 创建Runner Bean

最后,我们创建一个Runner 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. 测试结果

当我们在命令行中运行我们的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交互模型

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

通过这些交互模式,开发人员可以设计满足特定数据流、队列和应用程序行为要求的系统。

RSocket有四种主要的交互模式可供选择。这些方法之间的主要区别基于输入和输出的基数。

6.1. 请求-响应

在这种模式下,每个请求都会收到一个单一的响应。因此,我们使用了一个具有基数为一的Mono请求,并收到了一个具有相同基数的Mono响应。

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

6.2. 请求-流

当我们订阅新闻简讯时,通常会定期从服务器接收更新。当客户端发出初始请求时,服务器会以数据流作为响应。

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

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

6.3. 丢弃(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)

想象一个对讲机,允许双方同时进行双向通信,就像在交谈一样。这种类型的通信依赖于发送和接收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. 总结

在这篇文章中,我们详细探讨了Spring 6中新的声明式RSocket客户端功能。我们还了解了如何使用@RSocketExchange注解实现它。

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

最后,本教程的源代码可以在GitHub上找到。