# 10.5. RSocket

[RSocket](https://rsocket.io/)是一种用于字节流传输的二进制协议。它通过在单个连接上传递异步消息来实现对称交互模型。

Spring框架的模块`spring-messaging`为客户端和服务器端的RSocket请求者和响应者提供支持。有关更多详细信息，请参阅Spring 框架参考的[RSocket 部分](https://docs.spring.io/spring-framework/reference/6.1/rsocket.html#rsocket-spring)，包括 RSocket 协议的概述。

**10.5.1. RSocket 策略自动配置**

Spring Boot 自动配置一个`RSocketStrategies`bean，提供编码和解码 RSocket 有效负载所需的所有基础设施。默认情况下，自动配置将尝试配置以下内容（按顺序）：

1. Jackson 的[CBOR编解码器](https://cbor.io/)
2. Jackson 的 JSON 编解码器

`spring-boot-starter-rsocket`启动器提供了这两个依赖项。请参阅[Jackson 支持部分](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#features.json.jackson)以了解有关自定义可能性的更多信息。

开发人员可以通过创建`RSocketStrategies`实现`RSocketStrategiesCustomizer`接口的 bean 来自定义组件。请注意，它们的`@Order`很重要，因为它决定了编解码器的顺序。

**10.5.2. RSocket服务器自动配置**

Spring Boot 提供 RSocket 服务器自动配置。所需的依赖项由`spring-boot-starter-rsocket`提供.

Spring Boot 允许从 WebFlux 服务器通过 WebSocket 公开 RSocket，或者建立独立的 RSocket 服务器。这取决于应用程序的类型及其配置。

对于 WebFlux 应用程序（类型为`WebApplicationType.REACTIVE`），仅当以下属性匹配时，RSocket 服务器才会插入 Web 服务器：

```
spring.rsocket.server.mapping-path=/rsocket
spring.rsocket.server.transport=websocket
```

> 仅 Reactor Netty 支持将 RSocket 插入 Web 服务器，因为 RSocket 本身就是使用该库构建的。

或者，RSocket TCP 或 websocket 服务器作为独立的嵌入式服务器启动。除了依赖性要求之外，唯一需要的配置是为该服务器定义一个端口：

```
spring.rsocket.server.port=9898
```

**10.5.3. Spring Messaging RSocket 支持**

Spring Boot 将为 RSocket 自动配置 Spring Messaging 基础设施。

这意味着 Spring Boot 将创建一个`RSocketMessageHandler`bean 来处理对应用程序的 RSocket 请求。

**10.5.4. 使用 RSocketRequester 调用 RSocket 服务**

一旦服务器和客户端之间建立了`RSocket`通道，任何一方都可以向另一方发送或接收请求。

作为服务器，您可以在 RSocket `@Controller`的任何处理程序方法上注入`RSocketRequester`实例。作为客户端，您需要首先配置并建立RSocket连接。Spring Boot 会使用预期的编解码器自动配置`RSocketRequester.Builder`此类情况并应用任何`RSocketConnectorConfigurer`bean。

`RSocketRequester.Builder`实例是一个原型bean，这意味着每个注入点都会为您提供一个新实例。这是有意完成的，因为此构建器是有状态的，您不应使用同一实例创建具有不同设置的请求者。

下面的代码展示了一个典型的例子：

```
@Service
public class MyService {
​
    private final RSocketRequester rsocketRequester;
​
    public MyService(RSocketRequester.Builder rsocketRequesterBuilder) {
        this.rsocketRequester = rsocketRequesterBuilder.tcp("example.org", 9898);
    }
​
    public Mono<User> someRSocketCall(String name) {
        return this.rsocketRequester.route("user").data(name).retrieveMono(User.class);
    }
​
}
```
