Использование RSocket в Spring Boot

Spring Boot

1 Обзор

RSocketПоддержка протокола прикладного уровняReactive StreamsСемантика, например: используйте RSocket в качестве альтернативы HTTP. В этом уроке мы увидимRSocketИспользуется в весенней загрузке, особенно в том, как весенняя загрузка помогает абстрагироваться от API RSocket нижнего уровня.

2. Зависимость

Начнем с добавленияspring-boot-starter-rsocketЗависимость начинается:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-rsocket</artifactId>
</dependency>

Эта зависимость будет вытягиваться транзитивноRSocketСоответствующие зависимости, такие как:rsocket-coreиrsocket-transport-netty

3. Пример приложения

Теперь перейдем к нашему простому приложению. Чтобы выделитьRSocketПри условии интерактивного режима я намерен создать торговое приложение, торговое приложение включает в себя клиент и сервер.

3.1 Настройки сервера

Во-первых, мы настраиваем загрузку с помощью приложения Springboot.RSocket serverсервер. потому что этоspring-boot-starter-rsocket dependencyЗависимость, поэтому springboot автоматически настроитRSocket server. Как обычно, его можно изменить на основе свойств.RSocket serverЗначение конфигурации по умолчанию. Например: добавив следующую конфигурацию вapplication.properties, модифицироватьRSocketпорт

spring.rsocket.server.port=7000

Другие свойства сервера также могут быть дополнительно изменены по мере необходимости.

3.2 Настройка клиента

Далее давайте настроим клиент, который также является приложением Springboot. Хотя Springboot автоматически настраивает большинство компонентов, связанных с RSocket, для завершения настроек ему также необходимо настроить некоторые объекты.

@Configuration
public class ClientConfiguration {

    @Bean
    public RSocket rSocket() {
        return RSocketFactory
          .connect()
          .mimeType(MimeTypeUtils.APPLICATION_JSON_VALUE, MimeTypeUtils.APPLICATION_JSON_VALUE)
          .frameDecoder(PayloadDecoder.ZERO_COPY)
          .transport(TcpClientTransport.create(7000))
          .start()
          .block();
    }

    @Bean
    RSocketRequester rSocketRequester(RSocketStrategies rSocketStrategies) {
        return RSocketRequester.wrap(rSocket(), MimeTypeUtils.APPLICATION_JSON, rSocketStrategies);
    }
}

Здесь мы создаемRSocketКлиент и настройте порт TCP как: 7000. Примечание. Мы настроили сервисный порт ранее. Далее мы определяем объект декоратора RSocket.RSocketRequester. Этот объект находится в нашемRSocket serverПомогает нам при общении. После определения этих конфигураций объектов у нас есть только скелет. В следующем мы представим различные режимы взаимодействия и посмотрим, где может помочь Springboot.

4. springboot RSocketсерединаRequest/Response

мы начинаем сRequest/ResponseНачинать,HTTPЭтот способ общения также используется, который также является наиболее распространенным и наиболее похожим способом взаимодействия. В этом интерактивном режиме клиент инициирует связь и отправляет запрос. После этого сервер выполняет операцию и возвращает ответ клиенту — на этом связь завершена. В нашем торговом приложении клиент запрашивает текущие рыночные данные для данной акции. В ответ сервер передает запрошенные данные.

4.1 Сервер

На стороне сервера мы должны сначала создатьcontrollerдля хранения нашего метода обработчика. мы будем использовать@MessageMappingАннотации для замены, как в SpringMVC@RequestMappingили@GetMappingаннотация

@Controller
public class MarketDataRSocketController {

    private final MarketDataRepository marketDataRepository;

    public MarketDataRSocketController(MarketDataRepository marketDataRepository) {
        this.marketDataRepository = marketDataRepository;
    }

    @MessageMapping("currentMarketData")
    public Mono<MarketData> currentMarketData(MarketDataRequest marketDataRequest) {
        return marketDataRepository.getOne(marketDataRequest.getStock());
    }
}

Изучим наш контроллер. мы будем использовать@Controllerаннотация для определения контроллера для обработки входящих запросов RSocket. Кроме того, обратите внимание@MessageMappingДавайте определим интересующие нас маршруты и то, как отвечать на запрос. В этом примере сервер прослушивает маршрутcurrentMarketData, и ответьте одним результатомMono<MarketData>клиенту.

4.2 Клиент

Затем наш клиент RSocket должен запросить цену акции и получить один ответ. Чтобы инициировать запрос, мы должны использоватьRSocketRequesterкласса следующим образом:

@RestController
public class MarketDataRestController {

    private final RSocketRequester rSocketRequester;

    public MarketDataRestController(RSocketRequester rSocketRequester) {
        this.rSocketRequester = rSocketRequester;
    }

    @GetMapping(value = "/current/{stock}")
    public Publisher<MarketData> current(@PathVariable("stock") String stock) {
        return rSocketRequester
          .route("currentMarketData")
          .data(new MarketDataRequest(stock))
          .retrieveMono(MarketData.class);
    }
}

Примечание. В примереRSocketклиент также являетсяRESTСтильcontroller, чтобы получить доступ к нашемуRSocketсервер. Поэтому мы используем@RestControllerи@GetMappingаннотацию для определения наших конечных точек запроса/ответа. В методе конечной точки мы используем классRSocketRequesterи указать маршрут. По сути, это серверная частьRSocketНужный маршрут, а затем мы передаем данные запроса. Наконец, при вызовеretrieveMono()Метод Springboot поможет нам инициализировать взаимодействие запрос/ответ.

5. Spring Boot RSocketсерединаFire And Forgetмодель

Далее мы рассмотримFire And Forgetинтерактивный режим. Как следует из названия, клиент отправляет запрос на сервер, но не ожидает ответа от сервера. В нашей торговой программе некоторые клиенты будут служить источниками данных и отправлять рыночные данные на сервер.

5.1. Серверная часть

Давайте создадим еще одну конечную точку в нашем серверном приложении следующим образом:

@MessageMapping("collectMarketData")
public Mono<Void> collectMarketData(MarketData marketData) {
    marketDataRepository.add(marketData);
    return Mono.empty();
}

Еще раз определяем новый@MessageMappingперенаправляется какcollectMarketData. Кроме того, Spring Boot автоматически преобразует входящую полезную нагрузку вMarketDataпример. Однако большая разница здесь в том, что мы возвращаемMono<Void>, потому что клиенту не нужен возврат сервера.

5.2 Клиент

Давайте посмотрим, как мы инициализируем нашfire-and-forgetзапрос режима. Мы создадим еще одну конечную точку RESTful следующим образом:

@GetMapping(value = "/collect")
public Publisher<Void> collect() {
    return rSocketRequester
      .route("collectMarketData")
      .data(getMarketData())
      .send();
}

Здесь мы указываем, что маршрут и нагрузка будутMarketDataпример. Поскольку мы используемsend()метод заменыretrieveMono(), все режимы взаимодействия становятсяfire-and-forgetмодель.

6.Spring Boot RSocketсерединаRequest Stream

Поток запросов — это более сложный шаблон взаимодействия, в котором клиент отправляет запрос, но получает несколько ответов от сервера в течение определенного периода времени. Чтобы имитировать этот режим взаимодействия, клиент запрашивает все рыночные данные для данной акции.

6.1. Серверная часть

Начнем с серверной части. Мы добавим еще один метод карты сообщений следующим образом:

@MessageMapping("feedMarketData")
public Flux<MarketData> feedMarketData(MarketDataRequest marketDataRequest) {
    return marketDataRepository.getAll(marketDataRequest.getStock());
}

Как видите, этот метод-обработчик очень похож на другие методы-обработчики. Другая часть заключается в том, что мы возвращаемFlux<MarketData>заменитьMono<MarketData>. Наконец, наш сервер RSocket вернет несколько ответов клиенту.

6.2 Клиент

На стороне клиента мы должны создать конечную точку для инициации обмена запрос/ответ следующим образом:

@GetMapping(value = "/feed/{stock}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Publisher<MarketData> feed(@PathVariable("stock") String stock) {
    return rSocketRequester
      .route("feedMarketData")
      .data(new MarketDataRequest(stock))
      .retrieveFlux(MarketData.class);
}

Изучим запрос RSocket. Сначала мы определяем маршрут и запрашиваем полезную нагрузку. Затем мы определяем с помощьюretrieveFlux()Ожидаемый ответ на вызов. Эта часть определяет режим взаимодействия. Также обратите внимание: поскольку наш клиент такжеRESTсервер стилей, клиент также определяет тип носителя ответаMediaType.TEXT_EVENT_STREAM_VALUE.

7. Обработка исключений

Теперь давайте посмотрим, как исключения декларативно обрабатываются в серверной программе. При работе с запросом/ответом я могу просто использовать@MessageExceptionHandlerПримечания, как показано ниже:

@MessageExceptionHandler
public Mono<MarketData> handleException(Exception e) {
    return Mono.just(MarketData.fromException(e));
}

Здесь мы аннотируем метод обработки исключений как@MessageExceptionHandler. В результате этот метод будет обрабатывать все типы исключений, посколькуExceptionЯвляется суперклассом для всех других типов исключений. Мы также можем явно создать больше разных типов методов обработки исключений. Это, конечно, шаблон запроса/ответа, и мы возвращаемMono<MarketData>. Мы ожидаем, что тип ответа здесь будет соответствовать типу возврата нашей схемы взаимодействия.

8. Резюме

В этом руководстве мы представили поддержку Springboot RSocket и подробно описали различные режимы взаимодействия, предоставляемые RSocket. См. весь пример кода наGitHubначальство.

Оригинальная ссылка:Woohoo.Принеси арлингтонского терьера.com/spring-boot…

автор:baeldung

Переводчик: спать