Рубрики
Без рубрики

Ракета, Использующая Пружинный Ботинок

Узнайте, как использовать Rocket с помощью Spring Boot.

Автор оригинала: baeldung.

1. Обзор

RSocket – это протокол приложения, обеспечивающий семантику реактивных потоков-он функционирует, например, как альтернатива HTTP.

В этом уроке мы рассмотрим сокет, использующий Spring Boot , и, в частности, как он помогает абстрагироваться от API RSocket более низкого уровня.

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

Давайте начнем с добавления зависимости spring-boot-starter-rocket :


    org.springframework.boot
    spring-boot-starter-rsocket

Это приведет к транзитивному втягиванию зависимостей, связанных с ракетой, таких как rocket-core и socket-transport-netty .

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

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

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

Во-первых, давайте настроим сервер, который будет приложением Spring Boot, загружающим сервер сокетов.

Поскольку у нас есть зависимость spring-boot-starter-socket , Spring Boot автоматически настраивает для нас сервер сокетов. Как обычно при весенней загрузке, мы можем изменить значения конфигурации по умолчанию для сервера сокетов в зависимости от свойств.

Например, давайте изменим порт нашего сервера сокетов, добавив следующую строку в наш файл application.properties :

spring.rsocket.server.port=7000

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

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

Далее, давайте настроим клиент, который также будет приложением Spring Boot.

Хотя Spring Boot автоматически настраивает большинство компонентов, связанных с Ракетой, мы также должны определить некоторые компоненты для завершения настройки:

@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);
    }
}

Здесь мы создаем клиент Socket и настраиваем его для использования транспорта TCP на порту 7000. Обратите внимание, что это порт сервера, который мы настроили ранее.

Далее мы определяем R Socket Requester bean, который является оболочкой вокруг Socket . Этот компонент поможет нам при взаимодействии с сервером сокетов.

После определения этих конфигураций бобов у нас есть структура с голыми костями.

Далее мы рассмотрим различные модели взаимодействия и посмотрим, как Spring Boot поможет нам в этом.

4. Запрос/ответ с гнездом и пружинным загрузчиком

Давайте начнем с запроса/Ответа. Это, вероятно, самая распространенная и знакомая модель взаимодействия, поскольку HTTP также использует этот тип связи.

В этой модели взаимодействия клиент инициирует связь и отправляет запрос. После этого сервер выполняет операцию и возвращает ответ клиенту – таким образом, связь завершается.

В нашем приложении для трейдеров клиент запросит текущие рыночные данные по данной акции. В ответ сервер передаст запрошенные данные.

4.1. Сервер

На стороне сервера мы должны сначала создать контроллер для хранения наших методов обработчика. Но вместо @RequestMapping или @GetMapping аннотаций, как в Spring MVC, мы будем использовать @MessageMapping аннотацию :

@Controller
public class MarketDataRSocketController {

    private final MarketDataRepository marketDataRepository;

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

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

Итак, давайте исследуем наш контроллер.

Мы используем аннотацию @ Controller для определения обработчика, который должен обрабатывать входящие запросы сокетов. Кроме того, аннотация @MessageMapping позволяет нам определить, какой маршрут нас интересует и как реагировать на запрос.

В этом случае сервер прослушивает текущие рыночные данные маршрут, который возвращает клиенту один результат в виде Mono .

4.2. Клиент

Затем наш клиент Сокета должен запросить текущую цену акции и получить один ответ.

Чтобы инициировать запрос, мы должны использовать запрос сокета или класс:

@RestController
public class MarketDataRestController {

    private final RSocketRequester rSocketRequester;

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

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

Обратите внимание, что в нашем случае клиент сокета также является контроллером СБРОСА, из которого мы вызываем наш сервер сокетов. Итак, мы используем @RestController и @GetMapping для определения конечной точки запроса/ответа.

В методе конечной точки мы используем Запрос сокета R и указание маршрута. Фактически, это маршрут, который ожидает сервер сокетов. Когда мы передаем данные запроса. И, наконец, когда мы вызываем метод retrieve Mono () , Spring Boot инициирует взаимодействие запроса/ответа .

5. Огонь и Забудь С Ракетой и Пружинным Ботинком

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

В нашем приложении для трейдеров некоторые клиенты будут служить источником данных и будут передавать рыночные данные на сервер.

5.1. Сервер

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

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

Опять же, мы определяем новый @MessageMapping со значением маршрута сбор рыночных данных . Кроме того, Spring Boot автоматически преобразует входящую полезную нагрузку в экземпляр Market Data .

Однако большая разница здесь в том, что мы возвращаем Mono , поскольку клиенту не нужен ответ от нас.

5.2. Клиент

Давайте посмотрим, как мы можем инициировать наш запрос “огонь и забудь”.

Мы создадим еще одну конечную точку ОТДЫХА:

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

Здесь мы указываем наш маршрут, и нашей полезной нагрузкой будет экземпляр Market Data . Поскольку мы используем метод send() для инициирования запроса вместо retrieve Mono() , модель взаимодействия становится “огонь и забудь” .

6. Поток запросов с гнездом и пружинным загрузчиком

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

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

6.1. Сервер

Давайте начнем с нашего сервера. Мы добавим еще один метод сопоставления сообщений:

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

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

6.2. Клиент

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

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

Давайте рассмотрим наш запрос на сокет.

Во-первых, мы определяем маршрут и запрашиваем полезную нагрузку. Затем мы определяем наше ожидание ответа с помощью вызова метода retrieve Flux () /. Это та часть, которая определяет модель взаимодействия.

Также обратите внимание, что, поскольку наш клиент также является сервером REST, он определяет тип носителя ответа как Тип носителя.TEXT_EVENT_STREAM_VALUE.

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

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

При выполнении запроса/ответа мы можем просто использовать аннотацию @MessageExceptionHandler :

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

Здесь мы аннотировали наш метод обработчика исключений с помощью @MessageExceptionHandler . В результате он будет обрабатывать все типы исключений, поскольку класс Exception является суперклассом всех остальных.

Мы можем быть более конкретными и создавать различные методы обработки исключений для разных типов исключений.

Это, конечно, для модели запроса/ответа, и поэтому мы возвращаем Mono<Рыночные данные>. Мы хотим, чтобы наш тип возврата здесь соответствовал типу возврата нашей модели взаимодействия.

8. Резюме

В этом уроке мы рассмотрели поддержку сокетов Spring Boot и подробно описали различные модели взаимодействия, которые предоставляет сокет.

Как всегда, вы можете проверить все примеры кода на GitHub .