Статьи

Spring-Reactive образцы

Spring-Reactive направлен на обеспечение поддержки реактивного программирования для проектов, основанных на Spring, и ожидается, что это будет доступно в сроки Spring 5 . Мое намерение здесь состоит в том, чтобы использовать некоторые из самых основных сигнатур для конечных точек REST с этой моделью.

Прежде чем я продолжу, позвольте мне признать, что весь этот образец полностью основан на образцах, которые Себастьян Делез собрал здесь — https://github.com/sdeleuze/spring-reactive-playground

Я хотел рассмотреть три примера: во-первых, случай, когда существующее Java 8 CompletableFuture возвращается как тип, во-вторых, когда Observable в RxJava возвращается как тип, и в-третьих, с типом Flux Spring Reactor Core .

Ожидаемый протокол

Структура запроса и ответного сообщения, обрабатываемого каждой из трех служб, соответствует этим направлениям, все они будут принимать запрос, который выглядит следующим образом:

1
2
3
4
5
6
{
 "id":1,
  "delay_by": 2000,
  "payload": "Hello",
  "throw_exception": false
}

Delay_by сделает ответ задержанным, а throw_exception сделает ответ на ошибку. Разумный ответ будет следующим:

1
2
3
4
5
{
  "id": "1",
  "received": "Hello",
  "payload": "Response Message"
}

Я буду игнорировать исключения для этого поста.

CompletableFuture как тип возвращаемого значения

Рассмотрим сервис, который возвращает Java CompletableFuture 8 в качестве возвращаемого типа:

1
2
3
4
5
6
public CompletableFuture<MessageAcknowledgement> handleMessage(Message message) {
 return CompletableFuture.supplyAsync(() -> {
  Util.delay(message.getDelayBy());
  return new MessageAcknowledgement(message.getId(), message.getPayload(), "data from CompletableFutureService");
 }, futureExecutor);
}

Подпись метода Контроллера, который вызывает этот сервис, теперь выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
@RestController
public class CompletableFutureController {
 
 private final CompletableFutureService aService;
 
 @Autowired
 public CompletableFutureController(CompletableFutureService aService) {
  this.aService = aService;
 }
 
 @RequestMapping(path = "/handleMessageFuture", method = RequestMethod.POST)
 public CompletableFuture<MessageAcknowledgement> handleMessage(@RequestBody Message message) {
  return this.aService.handleMessage(message);
 }
 
}

Когда CompletableFuture завершит каркас, убедитесь, что ответ соответствующим образом перенаправлен обратно.

Rx Java Наблюдаемый как тип возврата

Рассмотрим сервис, который возвращает Rx Java Observable в качестве возвращаемого типа:

01
02
03
04
05
06
07
08
09
10
11
public Observable<MessageAcknowledgement> handleMessage(Message message) {
 logger.info("About to Acknowledge");
 return Observable.just(message)
   .delay(message.getDelayBy(), TimeUnit.MILLISECONDS)
   .flatMap(msg -> {
    if (msg.isThrowException()) {
     return Observable.error(new IllegalStateException("Throwing a deliberate exception!"));
    }
    return Observable.just(new MessageAcknowledgement(message.getId(), message.getPayload(), "From RxJavaService"));
   });
}

Контроллер, вызывающий такую ​​службу, теперь может напрямую возвращать Observable как тип, и инфраструктура будет гарантировать, что после того, как все элементы будут отправлены, ответ будет правильно распределен.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
@RestController
public class RxJavaController {
 
 private final RxJavaService aService;
 
 @Autowired
 public RxJavaController(RxJavaService aService) {
  this.aService = aService;
 }
 
 @RequestMapping(path = "/handleMessageRxJava", method = RequestMethod.POST)
 public Observable<MessageAcknowledgement> handleMessage(@RequestBody Message message) {
  System.out.println("Got Message..");
  return this.aService.handleMessage(message);
 }
 
}

Обратите внимание, что поскольку Observable представляет поток от 0 до многих элементов, на этот раз ответом является массив json.

Пружинный реактор Core Flux как тип возврата

Наконец, если тип ответа — тип Flux , структура гарантирует, что ответ обрабатывается аккуратно. Сервис по этим направлениям:

01
02
03
04
05
06
07
08
09
10
11
12
public Flux<messageacknowledgement> handleMessage(Message message) {
 return Flux.just(message)
   .delay(Duration.ofMillis(message.getDelayBy()))
   .map(msg -> Tuple.of(msg, msg.isThrowException()))
   .flatMap(tup -> {
    if (tup.getT2()) {
     return Flux.error(new IllegalStateException("Throwing a deliberate Exception!"));
    }
    Message msg = tup.getT1();
    return Flux.just(new MessageAcknowledgement(msg.getId(), msg.getPayload(), "Response from ReactorService"));
   });
}

и контроллер, использующий такую ​​услугу:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
@RestController
public class ReactorController {
 
 private final ReactorService aService;
 
 @Autowired
 public ReactorController(ReactorService aService) {
  this.aService = aService;
 }
 
 @RequestMapping(path = "/handleMessageReactor", method = RequestMethod.POST)
 public Flux<MessageAcknowledgement> handleMessage(@RequestBody Message message) {
  return this.aService.handleMessage(message);
 }
 
}

Вывод

Это просто выборка типов возвращаемых данных, поддерживаемых проектом Spring Reactive. Возможные типы возвращаемых значений намного больше этого — вот гораздо более полный пример.

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

Примеры, представленные в этом блоге, доступны в моем репозитории github.

Ссылка: Spring-Reactive образцы от нашего партнера JCG Биджу Кунджуммен в блоге all and sundry.