RSocket Los respondedores se pueden implementar como métodos con anotaciones @MessageMapping y @ConnectMapping. Los métodos anotados con @MessageMapping manejan solicitudes individuales, mientras que los métodos anotados con @ConnectMapping manejan eventos a nivel de conexión (configuración y envío de metadatos). Los respondedores anotados se admiten simétricamente tanto para las respuestas del lado del servidor como para las del lado del cliente.

Respondedores del lado del servidor

Para utilizar respondedores anotados del lado del servidor, agregue RSocketMessageHandler en la configuración de Spring para detectar beans marcados con la anotación @Controller con métodos anotados con @MessageMapping y @ConnectMapping:

Java

@Configuration
static class ServerConfig {
@Bean
public RSocketMessageHandler rsocketMessageHandler() {
RSocketMessageHandler handler = new RSocketMessageHandler();
handler.routeMatcher(new PathPatternRouteMatcher());
return handler;
}
}
Kotlin

@Configuration
class ServerConfig {
@Bean
fun rsocketMessageHandler() = RSocketMessageHandler().apply {
routeMatcher = PathPatternRouteMatcher()
}
}

Luego inicie el servidor RSocket a través de la API RSocket para Java y conecte el RSocketMessageHandler al respondedor de esta manera:

Java

ApplicationContext context = ... ;
RSocketMessageHandler handler = context.getBean(RSocketMessageHandler.class);
CloseableChannel server =
RSocketServer.create(handler.responder())
.bind(TcpServerTransport.create("localhost", 7000))
.block();
Kotlin

import org.springframework.beans.factory.getBean
val context: ApplicationContext = ...
val handler = context.getBean<RSocketMessageHandler>()
val server = RSocketServer.create(handler.responder())
.bind(TcpServerTransport.create("localhost", 7000))
.awaitSingle()
        

RSocketMessageHandler admite de forma predeterminada compuesto metadatos y enrutamiento. Puede configurar su MetadataExtractor si necesita cambiar a un tipo MIME diferente o registrar tipos de metadatos MIME adicionales.

Necesitará configurar el Encoder y el Decoder instancias, que son necesarias para admitir metadatos y formatos de datos. Para implementar códecs, lo más probable es que necesites el módulo spring-web.

De forma predeterminada, SimpleRouteMatcher se utiliza para negociar rutas a través de AntPathMatcher . Recomendamos conectar PathPatternRouteMatcher desde spring-web para una coincidencia de rutas eficiente. Las rutas de RSocket pueden ser jerárquicas, pero no son rutas de URL. Ambos comparadores de ruta están configurados para usar "." como delimitador predeterminado y no hay decodificación de URL como es el caso de las URL HTTP.

RSocketMessageHandler se puede configurar a través de RSocketStrategies, que puede ser útil si necesita compartir configuración entre cliente y servidor en el mismo proceso:

Java

@Configuration
static class ServerConfig {
@Bean
public RSocketMessageHandler rsocketMessageHandler() {
RSocketMessageHandler handler = new RSocketMessageHandler();
handler.setRSocketStrategies(rsocketStrategies());
return handler;
}
@Bean
public RSocketStrategies rsocketStrategies() {
return RSocketStrategies.builder()
    .encoders(encoders -> encoders.add(new Jackson2CborEncoder()))
    .decoders(decoders -> decoders.add(new Jackson2CborDecoder()))
    .routeMatcher(new PathPatternRouteMatcher())
    .build();
}
}
Kotlin

@Configuration
class ServerConfig {
@Bean
fun rsocketMessageHandler() = RSocketMessageHandler().apply {
rSocketStrategies = rsocketStrategies()
}
@Bean
fun rsocketStrategies() = RSocketStrategies.builder()
    .encoders { it.add(Jackson2CborEncoder()) }
    .decoders { it.add(Jackson2CborDecoder()) }
    .routeMatcher(PathPatternRouteMatcher())
    .build()
}

Contestadores del lado del cliente

Los respondedores anotados del lado del cliente deben configurarse en RSocketRequester.Builder .

@MessageMapping

Una vez que se ha configurado la configuración del respondedor para el servidor o cliente, los métodos con la anotación @MessageMapping se pueden usar de la siguiente manera:

Java
@Controller
public class RadarsController {
@MessageMapping("locate.radars.within")
public Flux<AirportLocation> radars(MapRequest request) {
// ...
}
}
Kotlin
@Controller
class RadarsController {
@MessageMapping("locate.radars.within")
fun radars(request: MapRequest): Flow<AirportLocation> {
// ...
}
}

El método anterior, marcado con anotación @MessageMapping, responde a una interacción de tipo Request-Stream con la ruta "locate.radars.within". Admite una firma de método flexible con la capacidad de utilizar los siguientes argumentos de método:

Argumento del método Descripción

@Payload

Solicitar carga útil. Puede ser un valor concreto de tipos asincrónicos como Mono o Flux.

Nota: El uso de una anotación es opcional. Un argumento de método que no es ni un tipo principal ni uno de los otros argumentos admitidos se considera la carga útil esperada.

RSocketRequester

Solicitante para transmitir solicitudes al lado receptor.

@DestinationVariable

El valor extraído de la ruta en función de las variables de la plantilla de mapeo, por ejemplo @MessageMapping("find.radar.{id}").

@Header

Valor de metadatos registrado para recuperar.

@Headers Map<String, Object>

Todos los valores de metadatos registrados para su recuperación.

Se espera que el valor de retorno sea uno o más objetos que se serializarán como datos de respuesta útiles. Estos pueden ser tipos asincrónicos como Mono o Flux, un valor concreto o void o un tipo asincrónico sin un valor como Mono<Void>.

El tipo de interacción RSocket que admite un método anotado con @MessageMapping está determinado por la cardinalidad del conjunto de entrada (es decir, el argumento anotado con @Payload) y salida, donde cardinalidad significa lo siguiente:

Poder del conjunto Descripción

1

Ya sea un valor explícito o un tipo de valor único asincrónico como Mono<T>.

Muchos

Un tipo asíncrono multivalor, como Flux<T>.

0

En el caso de input, esto significa que el método no tiene un argumento anotado con @Payload.

En el caso de la salida, esta es void o un tipo asincrónico sin valor como Mono<Void> .

La siguiente tabla muestra todas las combinaciones de potencia de conjuntos de entrada y salida y los tipos de interacción correspondientes:

Cardinalidad del conjunto de entradas Cardinalidad del conjunto de salida Tipos de interacción

0, 1

0

Disparar y olvidar, Solicitud-Respuesta

0, 1

1

Solicitud-Respuesta

0, 1

Establecer

Solicitud-Stream

Establecer

0, 1, establecer

Canal de solicitud

@ConnectMapping

La anotación @ConnectMapping maneja la SETUP marco al comienzo del establecimiento de una conexión RSocket y todas las notificaciones posteriores sobre cómo enviar metadatos a través del marco METADATA_PUSH, es decir, metadataPush(Payload) en io.rsocket.RSocket.

Los métodos con la anotación @ConnectMapping admiten los mismos argumentos que y métodos con la anotación @MessageMapping, pero se basan en metadatos y datos de los marcos SETUP y METADATA_PUSH. La anotación @ConnectMapping se puede proporcionar con una plantilla para limitar el procedimiento de procesamiento a conexiones específicas que tienen una ruta en los metadatos y, si no se declaran plantillas, todas las conexiones coincidirán.

Los métodos anotados @ConnectMapping no pueden devolver datos, por lo que deben declararse utilizando void o Mono<Void> como valor de retorno. Si el procedimiento de procesamiento devuelve un error para una nueva conexión, entonces la conexión se rechaza. El procedimiento de procesamiento no debe retrasarse para que se puedan realizar solicitudes a RSocketRequester para una conexión específica.