RSocket

RSocket 是一个用于字节流传输的二进制协议。 它通过单个连接上的异步消息传递实现对称交互模型。

Spring Framework 的 spring-messaging 模块提供了对 RSocket 请求者和响应者的支持,包括客户端和服务器端。 有关更多详细信息,包括 RSocket 协议的概述,请参阅 Spring Framework 参考文档中的 RSocket 部分

RSocket 策略自动配置

Spring Boot 自动配置一个 RSocketStrategies bean,该 bean 提供编码和解码 RSocket 负载所需的所有基础设施。 默认情况下,自动配置将尝试按以下顺序配置:

  1. 使用 Jackson 的 CBOR 编解码器

  2. 使用 Jackson 的 JSON 编解码器

spring-boot-starter-rsocket 启动器提供了这两个依赖项。 有关自定义可能性的更多信息,请参阅 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 Messaging 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
		)
	}

}