Предположим, что эти два сценария контроллера генерируют случайные числа с задержкой:
1) Реактивная пружина 5 реактивного применения:
@GetMapping("/randomNumbers")
public Flux<Double> getReactiveRandomNumbers() {
return generateRandomNumbers(10, 500);
}
/**
* Non-blocking randon number generator
* @param amount - # of numbers to generate
* @param delay - delay between each number generation in milliseconds
* @return
*/
public Flux<Double> generateRandomNumbers(int amount, int delay){
return Flux.range(1, amount)
.delayMillis(delay)
.map(i -> Math.random());
}
2) Традиционный Spring MVC с DeferredResult
:
@GetMapping("/randomNumbers")
public DeferredResult<Double[]> getReactiveRandomNumbers() {
DeferredResult<Double[]> dr = new DeferredResult<Double[]>();
CompletableFuture.supplyAsync(() -> {
return generateRandomNumbers(10, 500);
}).whenCompleteAsync((p1, p2) -> {
dr.setResult(p1);
});
return dr;
}
/**
* Blocking randon number generator
* @param amount - # of numbers to generate
* @param delay - delay between each number generation in milliseconds
* @return
*/
public Double[] generateRandomNumbers(int amount, int delay){
int generated = 0;
Double [] d = new Double[amount];
while(generated < amount){
try {
Thread.sleep(delay);
} catch (InterruptedException e) {}
d[generated] = Math.random();
generated++;
}
return d;
}
С точки зрения HTTP-клиента (браузер, AJAX-запрос) нет никакой разницы между обоими сценариями. Я имею в виду, что клиент будет ждать, пока все результаты не будут отправлены, и не будет обрабатывать их, пока не будет принят весь ответ.
То есть, хотя Spring Web Reactive заставляет нас думать, что он отправляет результаты обратно по мере их производства, в действительности этого не происходит, и клиент не сможет обработать результаты, пока все числа не получат был создан.
Простой способ сделать клиента полностью реактивным - использовать WebSockets.
Итак, кроме классных вещей (таких как хорошая семантика, композиция...), какой смысл использовать Spring Web Reactive, учитывая, что HTTP-запросы браузера не являются реактивными и эквивалентны использованию традиционного DeferredResult?