5.3. Annotated Responders

편집일시: 2021-04-12 14:18 조회수: 139 댓글수: 0
`RSocket` 응답자는 `@MessageMapping`와 `@ConnectMapping` 메소드로 구현할 수 있다. `@MessageMapping` 메소드는 개별 요청을 처리하고, `@ConnectMapping` 메소드가 연결 레벨의 이벤트(설치 및 메타 데이터 푸시)를 처리한다. 어노테이션이 선언된 응답자는 서버 측에서 응답과 클라이언트 측에서 응답을 위해 대칭적으로 지원된다. ## 5.3.1. 서버 응답자(Server Responders) 서버 측 어노테이션이 선언된 응답자를 사용하려면, `RSocketMessageHandler`를 Spring 설정에 추가하여 `@MessageMapping`와 `@ConnectMapping` 메소드에서 `@Controller` Bean을 검색한다. Java ``` @Configuration class ServerConfig { @Bean fun rsocketMessageHandler() = RSocketMessageHandler().apply { routeMatcher = PathPatternRouteMatcher() } } ``` Kotlin ``` @Configuration class ServerConfig { @Bean fun rsocketMessageHandler() = RSocketMessageHandler().apply { routeMatcher = PathPatternRouteMatcher() } } ``` 다음은 Java RSocket API를 사용하여 RSocket 서버를 시작하고 응답자의 `RSocketMessageHandler`를 다음과 같이 연결한다. Java ``` 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() ``` 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`는 기본적으로 [복합](https://github.com/rsocket/rsocket/blob/master/Extensions/CompositeMetadata.md) 메타 데이터와 [라우팅](https://github.com/rsocket/rsocket/blob/master/Extensions/Routing.md) 메타 데이터를 지원한다. 다른 MIME 타입으로 전환하거나, 추가 메타 데이터 MIME 유형을 등록해야하는 경우는 [MetadataExtractor](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-metadata-extractor)을 설정할 수 있다. 지원하는 메타 데이터 및 데이터 형식에 필요한 `Encoder`와 `Decoder` 인스턴스를 설정해야 한다. 코덱의 구현은 `spring-web` 모듈이 필요할 수 있다. 기본적으로 `SimpleRouteMatcher`는 `AntPathMatcher`를 통해 경로 매칭에 사용된다. 효율적인 경로 매칭을 위해 `spring-web` 부터 `PathPatternRouteMatcher`를 폐쇄하는 것을 권장한다. RSocket 루트는 계층화 할 수 있지만 URL 경로는 없다. 둘 모두 라우트 매처(route matchers)가 "."을 사용하도록 구성되어 있다. 기본적으로 구분자로 사용되며 HTTP URL 같은 URL 디코딩은 하지 않는다. `RSocketMessageHandler`은 이 같은 프로세스에서 클라이언트와 서버 사이에서 구성을 공유 할 필요가 있는 경우에 편리한 `RSocketStrategies` 을 통해 구성 할 수 있다. 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() } ``` ## 5.3.2. 클라이언트 응답자 클라이언트 측의 어노테이션이 선언된 응답자는 `RSocketRequester.Builder`로 구성해야 한다. 자세한 내용은 [클라이언트 응답자](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-requester-client-responder)를 참조해라. ## 5.3.3. @MessageMapping [서버](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-annot-responders-server) 또는 [클라이언트](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-annot-responders-server) 응답자의 설정이 완료되면, `@MessageMapping` 메소드를 다음과 같이 사용할 수 있다. Java ``` ``` Kotlin ``` @Controller class RadarsController { @MessageMapping("locate.radars.within") fun radars(request: MapRequest): Flow<AirportLocation> { // ... } } ``` 위에 있는 `@MessageMapping` 메소드는 "locate.radars.within"라는 라우팅 정보를 가진 Request-Stream 상호 작용에 응답한다. 다음의 메소드 인수를 사용하는 옵션을 가진 유연한 메소드 시그너처를 지원하고 있다. | 메소드 인수 | 설명| |--|--| | `@Payload` | 요청의 페이로드. 이는 `Mono`와 `Flux` 등의 비동기 유형의 구체적인 값이다. **주의** : 어노테이션 사용은 옵션이다. 단순 형식이 아니라 지원되는 다른 인자 중의 하나가 아니면, 메소드 인수는 예상 페이로드로 간주된다. | | `RSocketRequester` | 원격 종료를 요청하는 요청자. | | `@DestinationVariable` | 매핑 패턴의 변수에 따라 루트에서 추출된 값. `@MessageMapping("find.radar.{id}")` | | `@Header` | [MetadataExtractor](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-metadata-extractor)에서 언급된 추출을 위해 등록된 메타 데이터 값. | | `@Headers Map<String, Object>` | [MetadataExtractor](https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html#rsocket-metadata-extractor) 따라 추출에 등록된 모든 메타 데이터 값. | 반환 값은 응답 페이로드로 직렬화되는 하나 이상의 오브젝트 일 것으로 예상된다. 이는 `Mono` , `Flux`와 같은 비동기 타입이거나 구체적인 값 또는 `void`, `Mono<Void>`와 같은 값이 없는 비동기 타입 중 하나이다. `@MessageMapping` 메소드가 지원하는 RSocket 상호 작용 유형은 입력(즉, `@Payload` 인수)와 출력 카디널리티에서 결정된다. 카디널리티는 다음을 의미한다. | 기수 | 설명 | |--|--| | 1 | 명시적인 값 또는 `Mono<T>` 같은 단일 값 비동기 유형 중 하나. | | Many | `Flux<T>` 등의 여러 값 비동기 타입. | | 0 | 입력의 경우,이 메서드에 `@Payload` 인수가 없음을 의미한다. 출력의 경우, 이는 `void`, `Mono<Void>`와 같은 값이 없는 비동기 유형이다. | 다음 표는 모든 입력 및 출력 중요도의 조합과 대응하는 상호 작용 유형을 보여준다. | 입력 카디널리티 | 출력 카디널리티 | 상호 작용 유형 | |--|--|--| | 0, 1 | 0 | 단방향 메시지 요청과 응답 | | 0, 1 | 1 | Request-Response | | 0, 1 | Many | Request-Stream | | Many | 0, 1, Many | Request-Channel | ## 5.3.4. `@ConnectMapping` `@ConnectMapping`는 RSocket 연결을 시작할 때 `SETUP` 프레임을 처리하며 이어서 메타 데이터는 `METADATA_PUSH` 프레임, 즉 `io.rsocket.RSocket`의 `metadataPush(Payload)`를 통해 알림을 푸시한다. `@ConnectMapping` 메소드는 `@MessageMapping`과 같은 인수를 지원하고 있지만, `SETUP`, `METADATA_PUSH` 프레임에서 메타 데이터와 데이터를 기반으로 한다. `@ConnectMapping` 메타 데이터 경로를 사용하여 지정된 연결에 처리 수정 패턴을 설정할 수 있다. 패턴이 선언되지 않은 경우 모든 연결이 일치한다. `@ConnectMapping` 메소드는 데이터를 반환 할 수 없으며 반환으로 `void`, `Mono<Void>`를 사용하여 선언해야 한다. 새 연결에 대한 처리가 오류를 반환하면 연결이 거부된다. 연결에 대한 `RSocketRequester` 요청을 수행하기 위해 처리를 지연되지 않는다. 자세한 내용은 서버 요청자 를 참조해라.

이전 글 : 5.2. RSocketRequester
다음 글 : 5.4. MetadataExtractor