spring-webflux真 · 流式编程

云中志

共 4296字,需浏览 9分钟

 · 2021-07-31

前言

今天我们来看下webflux比较奇特的操作。当然这些操作,在我们以前的web应用中很难实现的,至少实现起来并不容易。

webflux

下面是一个webflux流式编程的典型样例,简单来说就是,前端请求一次,收到请求后会源源不断地向前端传输数据。

这感觉就像我们的水管一样,前端发送一个开启传输的指令,然后后端就开始像放水一样像前端传输数据了。

接口配置

下面是接口的实现,这里和我们前面分享的接口有所不同,这里响应数据传输的容器用的是Flux,之前都用的是Mono。关于两者的区别,根据我查到的资料,Mono一般用于返回01个元素的异步序列Publisher,也就和我们传统的MVC很像;而Flux时返回0或者N个元素组成的PublisherPublisher的作用类似于消息分发中心这样的角色,核心方法是subscribe

 public Mono<ServerResponse> sendTimePerSec(ServerRequest serverRequest) {
        return ServerResponse.ok().contentType(MediaType.TEXT_EVENT_STREAM).body(  // 1
                Flux.interval(Duration.ofSeconds(1)).   // 2
                        map(l -> new SimpleDateFormat("HH:mm:ss").format(new Date())),
                String.class);
    }

这个接口的作用是,间隔一秒向前端发送当前时间,时间格式HH:mm:ss

这里需要注意的是,这里的请求头设置的是TEXT_EVENT_STREAM,这种响应头和之前的区别后面我们会演示,这里大家留意下就行。

interval是一个延迟回调方法,当达到指定的延迟时间period,方法返回值是循环的次数,从0开始。下面是官方文档给出的interval方法的示意图,还是比较形象的

map方法应该不需要过多说明吧,用过lambda表达式的小伙伴,应该很熟悉,在这里它的作用也是做类型转换,这里的写法是lambda的写法,完整写法是这样的:

.map(new Function<Long, String>() {
                    @Override
                    public String apply(Long l) {
                        System.out.println(l);
                        return new SimpleDateFormat("HH:mm:ss").format(new Date());
                    }
                })

路由配置

这里是设置我们接口的路由信息,包括请求方式、地址、处理器等。

@Bean
    public RouterFunction<ServerResponse> routSayHi(HiHandler handler) {
        return RouterFunctions
                .route(RequestPredicates.GET("webflux/hi")
                        .and(RequestPredicates.accept(MediaType.ALL)), handler::sayHi)
                .andRoute(RequestPredicates.GET("/webflux/test")
                        .and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), handler::sendTimePerSec);
    }

测试运行

访问我们的接口,你会发现,虽然前端只访问了一次,数据一直在持续输出,当然如果你点击浏览器上面的X,就相当于本次请求结束,数据也就不再传输了。

而且后端也在持续输出,就像水管一样,水一直在流动。

另外根据我们运行结果来看,我们发现Flux类型的响应数据和之前的响应类型(Mono)相比是不一样的,在Flux的响应数据中,我们会发现接口的响应头变成了text/event-stream;charset=UTF-8,也就是我们前面执行的响应头,而且多了一个请求头transfer-encoding: chunked,这个请求头表明我们的响应数据长度是不确定的,据说这种方式占用的资源更少,可以让数据一块一块输出。

关于两者区别,我暂时还不清楚,但是如果把Mono的响应体改成TEXT_EVENT_STREAM,返回结果依然正常,但是如果把Flux的响应类型改成APPLICATION_JSON,虽然页面依然会持续有数据输出,但是看起来比刚才奇怪了:

好了, 关于webflux的流式编程就先演示到这里,后面我们看情况继续深入。

总结

经过这几天的摸索和学习,我慢慢对webflux有了更深入的了解和认识,但是同时也发现webflux的相关只是真的是太多了,而且是越学习感觉不知道的东西越多(知识的悖论,知识的诅咒),所以也只能说自己以前想的太天真了,竟然还想通过三五天的时间就学会webflux

另外,我也发现目前市面上关于webflux的相关知识、书籍和博客都比较少,而且大部分都不够系统,所以关于webflux的学习,我已经做好了持久战的准备,以后应该不会每天更新,这样确实比较容易上头,另一方面,如果积累的知识点不够的话,很容易言之无物,所以综合起来看,拉长战线会是一个比较合理的选择。

最后,给各位i小伙伴一个建议,在学习的时候,一定要定期去复习,不然之前学习的知识点比较容易忘记。这两天我在用线程池的时候,还专门去翻了之前的博客,因为好多东西又忘了

- END -


浏览 72
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报