RSocket
RSocket 是一种用于字节流传输的二进制协议。它通过单一连接上的异步消息传递实现了对称的交互模型。
Spring 框架的 spring-messaging
模块提供了对 RSocket 请求者和响应者的支持,无论是在客户端还是服务器端。有关更多详细信息,包括 RSocket 协议的概述,请参阅 Spring 框架参考文档中的 RSocket 部分。
RSocket 策略自动配置
Spring Boot 自动配置了一个 RSocketStrategies bean,它提供了编码和解码 RSocket 负载所需的所有基础设施。默认情况下,自动配置会尝试按顺序配置以下内容:
-
使用 Jackson 的 CBOR 编解码器
-
使用 Jackson 的 JSON 编解码器
spring-boot-starter-rsocket
starter 提供了这两个依赖项。有关自定义可能性的更多信息,请参阅 Jackson 支持部分。
开发者可以通过创建实现 RSocketStrategiesCustomizer 接口的 Bean 来自定义 RSocketStrategies 组件。需要注意的是,它们的 @Order 注解很重要,因为它决定了编解码器的顺序。
RSocket 服务器自动配置
Spring Boot 提供了 RSocket 服务器的自动配置。所需的依赖由 spring-boot-starter-rsocket
提供。
Spring Boot 允许在 WebFlux 服务器上通过 WebSocket 暴露 RSocket,或者建立一个独立的 RSocket 服务器。这取决于应用程序的类型及其配置。
对于 WebFlux 应用(即类型为 WebApplicationType.REACTIVE),RSocket 服务器只有在以下属性匹配时才会嵌入到 Web 服务器中:
- Properties
- YAML
spring.rsocket.server.mapping-path=/rsocket
spring.rsocket.server.transport=websocket
spring:
rsocket:
server:
mapping-path: "/rsocket"
transport: "websocket"
将 RSocket 插入到 Web 服务器时,仅支持 Reactor Netty,因为 RSocket 本身是基于该库构建的。
另外,也可以将 RSocket TCP 或 WebSocket 服务器作为一个独立的嵌入式服务器启动。除了依赖需求外,唯一需要的配置就是为该服务器定义一个端口:
- Properties
- YAML
spring.rsocket.server.port=9898
spring:
rsocket:
server:
port: 9898
Spring 消息传递 RSocket 支持
Spring Boot 将自动配置 RSocket 的 Spring Messaging 基础设施。
这意味着 Spring Boot 将创建一个 RSocketMessageHandler bean,该 bean 将处理发送到应用程序的 RSocket 请求。
使用 RSocketRequester 调用 RSocket 服务
一旦在服务器和客户端之间建立了 RSocket 通道,任何一方都可以向另一方发送或接收请求。
作为服务器,您可以在 RSocket @Controller 的任何处理器方法中注入一个 RSocketRequester 实例。作为客户端,您需要首先配置并建立 RSocket 连接。Spring Boot 为此类情况自动配置了一个 RSocketRequester.Builder,并应用了预期的编解码器以及任何 RSocketConnectorConfigurer bean。
RSocketRequester.Builder 实例是一个原型 Bean,这意味着每个注入点都会为你提供一个新实例。这是有意为之的,因为这个构建器是有状态的,你不应该使用同一个实例创建具有不同配置的请求器。
以下代码展示了一个典型的示例:
- Java
- Kotlin
import reactor.core.publisher.Mono;
import org.springframework.messaging.rsocket.RSocketRequester;
import org.springframework.stereotype.Service;
@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);
}
}
import org.springframework.messaging.rsocket.RSocketRequester
import org.springframework.stereotype.Service
import reactor.core.publisher.Mono
@Service
class MyService(rsocketRequesterBuilder: RSocketRequester.Builder) {
private val rsocketRequester: RSocketRequester
init {
rsocketRequester = rsocketRequesterBuilder.tcp("example.org", 9898)
}
fun someRSocketCall(name: String): Mono<User> {
return rsocketRequester.route("user").data(name).retrieveMono(
User::class.java
)
}
}