当通量从弹簧卷筒纸控制器返回时会发生什么? [英] What happens when flux is returned from spring web controller?

查看:10
本文介绍了当通量从弹簧卷筒纸控制器返回时会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对反应式API比较陌生,当我们从Web控制器返回Flux时,我很好奇幕后发生了什么。

根据Spring-Web文档

反应返回值的处理方式如下:

适用于单值承诺,类似于使用DeferredResult。例如Mono(反应堆)或Single(RxJava)。

适配流媒体类型的多值流(如应用程序/流+json或文本/事件流),类似于使用ResponseBodyEmitter或SseEmitter。例如,通量(反应堆)或可观测(RxJava)。应用程序还可以返回Flux或Observable。

适应任何其他媒体类型(如应用程序/json)的多值流,类似于使用DeferredResult<List<?>>

我创建了两个接口,如下:

@GetMapping("/async-deferredresult")
public DeferredResult<List<String>> handleReqDefResult(Model model) {
    LOGGER.info("Received async-deferredresult request");
    DeferredResult<List<String>> output = new DeferredResult<>();

    ForkJoinPool.commonPool().submit(() -> {
        LOGGER.info("Processing in separate thread");
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 10000   ; i++) {
            list.add(String.valueOf(i));
        }
        output.setResult(list);
    });

    LOGGER.info("servlet thread freed");
    return output;
}


@GetMapping(value = "/async-flux",produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
    LOGGER.info("Received async-deferredresult request");
    List<String> list = new ArrayList<>();
    list.stream();
    for (int i = 0; i < 10000   ; i++) {
        list.add(String.valueOf(i));
    }
    return Flux.fromIterable(list);
}

因此例外情况是,这两个API的行为应该与多值流(Flux)的行为相同,与返回DeferredResult的行为相似。
但在返回延迟结果的API中,在浏览器上一次打印整个列表,就像在返回Flux的API中一样,按顺序(逐个)打印数字。
当我从控制器返回通量时,到底发生了什么?

推荐答案

当我们从服务终结点返回通量时,可能会发生许多事情。但我假设您想知道当Flux观察到来自此终结点的客户端的事件流时发生了什么。

场景一:通过添加‘APPLICATION/json’作为终结点的内容类型,Spring将与预期JSON正文的客户端进行通信。

@GetMapping(value = "/async-flux", produces = MediaType.APPLICATION_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 10000; i++) {
        list.add(String.valueOf(i));
    }
    return Flux.fromIterable(list);
}

客户端的输出将是一整套数字。一旦发送了响应,连接就会关闭。即使您已经使用了Flux作为响应类型,您仍然受到基于TCP/IP的HTTP的工作原理的约束。端点收到一个HTTP请求,执行逻辑并使用包含最终结果的HTTP响应进行响应。

因此,您看不到反应性API的实际价值。

场景2:通过添加‘APPLICATION/STREAM+json’作为端点的内容类型,Spring开始将Flux流的结果事件视为单独的JSON项。当发出项时,它将被序列化,并刷新HTTP响应缓冲区,并且从服务器到客户端的连接保持打开,直到事件序列完成。

要使其正常工作,我们可以稍微修改您的原始代码,如下所示。

@GetMapping(value = "/async-flux",produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
public Flux<String> handleReqDefResult1(Model model) {
    List<String> list = new ArrayList<>();
    for (int i = 0; i < 10000   ; i++) {
        list.add(String.valueOf(i));
    }
    return Flux.fromIterable(list)
            // we have 1 sec delay to demonstrate the difference of behaviour. 
            .delayElements(Duration.ofSeconds(1));
}

这一次,我们可以看到Active API终结点的实际价值,在该终结点上,它能够在日期可用时将结果传递给其客户端。

有关如何构建反应式REST API的更多详细信息,请访问 https://medium.com/@senanayake.kalpa/building-reactive-rest-apis-in-java-part-1-cd2c34af55c6 https://medium.com/@senanayake.kalpa/building-reactive-rest-apis-in-java-part-2-bd270d4cdf3f

这篇关于当通量从弹簧卷筒纸控制器返回时会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆