RSocket

RSocket 是一種二進制協議,用於位元組流傳輸。它通過單一連線上的異步訊息傳遞實現對稱的互動模型。

Spring Framework 的 spring-messaging 模組為客戶端和伺服器端的 RSocket 請求者和響應者提供支援。有關更多詳細資訊,包括 RSocket 協議的概述,請參閱 Spring Framework 參考文件的 RSocket 章節

RSocket Strategies 自動組態

Spring Boot 自動組態一個 RSocketStrategies bean,它為編碼和解碼 RSocket 有效負載提供所有必需的基礎架構。 預設情況下,自動組態將嘗試配置以下項目(依序):

  1. CBOR 編解碼器與 Jackson

  2. JSON 編解碼器與 Jackson

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 伺服器中:

  • 屬性

  • YAML

spring.rsocket.server.mapping-path=/rsocket
spring.rsocket.server.transport=websocket
spring:
  rsocket:
    server:
      mapping-path: "/rsocket"
      transport: "websocket"
只有 Reactor Netty 才支援將 RSocket 插入 Web 伺服器,因為 RSocket 本身就是使用該程式庫建構的。

或者,RSocket TCP 或 websocket 伺服器作為獨立的嵌入式伺服器啟動。 除了依賴項要求外,唯一需要的組態是為該伺服器定義埠:

  • 屬性

  • YAML

spring.rsocket.server.port=9898
spring:
  rsocket:
    server:
      port: 9898

Spring Messaging RSocket 支援

Spring Boot 將為 RSocket 自動組態 Spring Messaging 基礎架構。

這表示 Spring Boot 將創建一個 RSocketMessageHandler 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
		)
	}

}