Spring Boot 2.x实战53 - Spring Web MVC 25 - 异步请求(HTTP Streaming - ResponseBodyEmitter)

5.2 HTTP Streaming

DeferredResultCallable只能异步返回单个值;如果我们想有多个异步返回的话,我们可以用HTTP Streaming来实现。

HTTP Streaming是一种推送形式的数据传输技术,它通过无限期开放的HTTP连接让web服务器(tomcat)能持续向客户端(浏览器)传送数据。

HTTP Streaming下,web服务器会握住客户端的请求并让返回保持开放,这样服务器可以通过返回一直发送数据。这个请求-返回的通道会一直开启,除非我们显示的要求关闭。

5.2.1 ResponseBodyEmitter

我们可以使用ResponseBodyEmitter作为返回值返回数据对象的流。我们可以用ResponseEntity来包装ResponseBodyEmitter,这样我们可以定制返回的状态和头信息。

我们定义本里所需的控制器方法,这个例子和DeferredResult类似:

@RestController
@RequestMapping("/async")
@Slf4j
public class AsyncController {

    private static Map<Long, ResponseBodyEmitter> responseBodyEmitterMap = new HashMap<>();

    @GetMapping(value = "/{id}/rbe") //1
    public ResponseEntity<ResponseBodyEmitter> responseBodyEmitter(@PathVariable Long id){
        ResponseBodyEmitter emitter = new ResponseBodyEmitter(); 
        responseBodyEmitterMap.put(id, emitter);
        return ResponseEntity
                .ok()
                .contentType(MediaType.TEXT_HTML) 
                .body(emitter); //2

    }

    @GetMapping("/{id}/invoke-rbe") //3
    public void invokeResponseBodyEmitter(@PathVariable Long id) throws Exception {
        ResponseBodyEmitter emitter = responseBodyEmitterMap.get(id); //4
        emitter.send("Hello World", MediaType.TEXT_PLAIN); //5
        Thread.sleep(1000); 
        emitter.send(new Person(1l, "wyf", 35), MediaType.APPLICATION_JSON); 
        Thread.sleep(1000);
        emitter.send(new Person(2l,"foo", 40), MediaType.APPLICATION_XML); 
        Thread.sleep(1000);
        emitter.send(new AnotherPerson(3l,"bar", 50), new MediaType("application","another-person"));
    }

    @GetMapping("/{id}/close-rbe") //6
    public void closeResponseBodyEmitter(@PathVariable Long id) throws IOException {
        ResponseBodyEmitter emitter = responseBodyEmitterMap.get(id);
        emitter.complete(); //7
        responseBodyEmitterMap.remove(id);
    }
}
  1. 定义此控制器接受web请求;
  2. 使用ResponseEntity包装ResponseBodyEmitter对象作为返回值,状态为为OK,头信息制定内容内省为HTML,这样我们的返回能直接显示在浏览器;
  3. 定义此控制器异步发送信息;
  4. 从map中获取ResponseBodyEmitter对象;
  5. 通过ResponseBodyEmittersend(Object object,MediaType mediaType)方法来发送数据;第一个参数要发送的数据,第二个参数指定该条数据的数据类型从而选用对应的HttpMessageConverter来转换数据;
  6. 定义此控制器关闭ResponseBodyEmitter对象;
  7. 通过ResponseBodyEmittercomplete()方法来关闭ResponseBodyEmitter

此时我们用浏览器访问https://localhost:8443/async/1/rbe,这时浏览器处于等待的状态;当我们访问https://localhost:8443/async/1/invoke-rbe,这时浏览器每隔一秒会输出相应的内容,刷新后会再次输出。
Spring Boot 2.x实战53 - Spring Web MVC 25 - 异步请求(HTTP Streaming - ResponseBodyEmitter)_第1张图片
当我们访问https://localhost:8443/async/1/close-rbe关闭连接,https://localhost:8443/async/1/rbe结束等待状态,再刷新https://localhost:8443/async/1/invoke-rbe就没有输出了。
Spring Boot 2.x实战53 - Spring Web MVC 25 - 异步请求(HTTP Streaming - ResponseBodyEmitter)_第2张图片

新书推荐:

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html

在这里插入图片描述
主要包含目录有:

第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和屁股里(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。

你可能感兴趣的:(Spring,Boot2.x实战,-,Spring,MVC,Spring,Boot2.x实战全集)