Spring WebFlux 响应式编程学习笔记(一)

各位Javaer们,大家都在用SpringMVC吧?当我们不亦乐乎的用着SpringMVC框架的时候,Spring5.x又悄(da)无(zhang)声(qi)息(gu)的推出了Spring WebFlux。web? 不是已经有SpringMVC这么好用的东西了么,为啥又冒出个WebFlux? 这玩意儿是什么鬼?

Spring WebFlux特性

异步非阻塞

SpringMVC是同步阻塞的IO模型,资源浪费相对来说比较严重,当我们在处理一个比较耗时的任务时,例如:上传一个比较大的文件,首先,服务器的线程一直在等待接收文件,在这期间它就像个傻子一样等在那儿(放学别走),什么都干不了,好不容易等到文件来了并且接收完毕,我们又要将文件写入磁盘,在这写入的过程中,这根线程又再次懵bi了,又要等到文件写完才能去干其它的事情。这一前一后的等待,不浪费资源么?

没错,Spring WebFlux就是来解决这问题的,Spring WebFlux可以做到异步非阻塞。还是上面那上传文件的例子,Spring WebFlux是这样做的:线程发现文件还没准备好,就先去做其它事情,当文件准备好之后,通知这根线程来处理,当接收完毕写入磁盘的时候(根据具体情况选择是否做异步非阻塞),写入完毕后通知这根线程再来处理(异步非阻塞情况下)。这个用脚趾头都能看出相对SpringMVC而言,可以节省系统资源。666啊,有木有!

响应式(reactive)函数编程

如果你觉得java8的lambda写起来很爽,那么,你会再次喜欢上Spring WebFlux,因为它支持函数式编程,得益于对于reactive-stream的支持(通过reactor框架来实现的),喜欢java8 stream的又有福了。为什么要函数式编程? 这个别问我,我也不知道,或许是因为bi格高吧,哈哈,开玩笑啦。

不再拘束于Servlet容器

以前,我们的应用都运行于Servlet容器之中,例如我们大家最为熟悉的Tomcat, Jetty...等等。而现在Spring WebFlux不仅能运行于传统的Servlet容器中(前提是容器要支持Servlet3.1,因为非阻塞IO是使用了Servlet3.1的特性),还能运行在支持NIO的Netty和Undertow中。

所以,看完Spring WebFlux的新特性之后,内心五味杂陈的我,只能用一个表情来形容:

bq__%E4%BB%80%E4%B9%88%E7%8E%A9%E6%84%8F.jpg

但是学习还是要学的,毕竟Spring推出的......

Spring WebFlux是随Spring 5推出的响应式Web框架。建立在异步非阻塞的IO框架之上的一个新的,其基本的架构如下:
getImage?fileId=5a929813ab644121e3000f8c

Spring提供了完整的支持响应式的服务端技术栈。

如上图所示,左侧为基于spring-webmvc的技术栈,右侧为基于spring-webflux的技术栈,可以看到SpringMVC技术栈给予Serverlet容器,如Tomcat容器,SpringWebFlux基于HTTP/Reactive Stream.

WebFlux 依赖构建

依赖于SpringBoot的强大,我们只要在配置文件添加依赖即可。

Gradle 依赖

    compile('org.springframework.boot:spring-boot-starter-webflux')

或者Maven构建的依赖于

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

SpringMVC注解方式实现

Spring团队在开发WebFlux上尽量和SpringMVC靠拢,因此我们可以直接使用一个简单的SpringMVC项目有改造成Spring WebFlux的项目,具体如下。

改造 Spring MVC

下面是我们再熟悉不过的接口应用,访问http://localhost:8080/mono 即可看到返回了一个字符串

   @GetMapping("/mono")public String baseApi() {return "Hello,Reactive Program";}

改造后的内容如下:

    @GetMapping("/mono")public Mono<String> baseApi() {                  //1return Mono.just("Hello,Reactive Program");   //2}

主要有两处改造

  • 1 返回的不再是简单的对象,而是使用的是Mono封装的单个文档信息(返回集合使用Flux)

  • 2 返回的时候我们需要构造一个Mono类型的数据,因此使用Mono.just(T t) 构造

可以看大,执行的结果如下:

$ curl -X GET http://localhost:8080/mono
Hello,Reactive Program

效果和SpringMVC 并无区别,同样的我们返回集合列表查看效果

    @GetMapping("/flux")public Flux<String> getFluxString() {String[] dataSet = new String[]{"This is 1", "This is 2", "This is 3", "This is 4"};return Flux.fromIterable(Arrays.asList(dataSet));}

分析过程

结果也和预期一致,那么不仅要思考了,同样和SpringMVC达到一致的效果,为什么我们要用WebFlux?

首先看着这两者并无区别,其实实际上和文章首页的架构图示一样,其底层核心的变了,实现接口,并再是基于Servlet,而是基于Http/Reactive Stream ,我们在接口方法添加参数

    @GetMapping("/flux")public Flux<String> getFluxString(HttpServerRequest request) {....}

此时访问flux接口,会报错

java.lang.IllegalStateException: No primary or default constructor found for interface org.springframework.http.HttpRequest

意思是非法的状态异常,没有org.springframework.http.HttpRequest的构造参数被发现,这说明WebFlux的实现已经不再是Serverlet了

实现Server Send Event

下面我是实现SSE(服务器推送),注意这里和Socket有所区别,Socket是双向通信,这是单向通信,由服务器向客户端推送消息

    @GetMapping(value = "/sse/object", produces = MediaType.TEXT_EVENT_STREAM_VALUE)public Flux<Book> sseBook() {return Flux.interval(Duration.ofSeconds(1)).map(second ->new Book().setId(Stirng.valueOf(second)).setName("深入浅出Flux响应式Web编程" + second).setPrice("12")).take(5);}

模型Book需要lombok支持,没有的话,请手动完成set、get方法,并在Set方法尾部return this


@Data
@Accessors(chain = true)
public class Book {private String id;private String name;private String price;private Date createTime = new Date();
}

首先说明一下produces = MediaType.TEXT_EVENT_STREAM_VALUE 表示这是一个事件流,返回的是Flux类型,推送的间隔为1s,最后take(times)表示推送的次数,没有take表示无限流,times表示推送的次数,我们在shell中尝试调用下,看看效果

$ curl -X GET http://localhost:8080/sse/object
data:{"id":"0","name":"Flux响应式Web编程0","price":"12","createTime":"2018-09-09T12:46:10.445+0000"}data:{"id":"1","name":"Flux响应式Web编程1","price":"12","createTime":"2018-09-09T12:46:11.444+0000"}data:{"id":"2","name":"Flux响应式Web编程2","price":"12","createTime":"2018-09-09T12:46:12.444+0000"}data:{"id":"3","name":"Flux响应式Web编程3","price":"12","createTime":"2018-09-09T12:46:13.445+0000"}data:{"id":"4","name":"Flux响应式Web编程4","price":"12","createTime":"2018-09-09T12:46:14.444+0000"}

需要注意的是,在创建时间上,是每个1s钟由服务器推送过来的,这是和SpringMVC有着巨大的区别.

RouterFunctin 实现方式

Spring团队在实现WebFlux的有了另外的实现方式,利用RouterFuntion & HandleFunction,这里不做过多的赘述,这种方式的效果和上述效果一致,可以对比学习,代码如下:

向Spring容器中注入RouterFunctionBean对象

@Configuration
public class RouteConfig {@Beanpublic RouterFunction<ServerResponse> timeRoute(){return route(GET("/time"),TimeHandle::getTime).andRoute(GET("/sse"),TimeHandle::sendTimeWithSSE);}
}

具体逻辑实现

public class TimeHandle {private static SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");public static Mono<ServerResponse>  getTime(ServerRequest serverRequest){return ok().contentType(MediaType.APPLICATION_JSON_UTF8).body(Mono.just(simpleDateFormat.format(new Date())),String.class);}// 实现时间SSE推送注意MediaType类型public static Mono<ServerResponse> sendTimeWithSSE(ServerRequest serverRequest){return  ok().contentType(MediaType.TEXT_EVENT_STREAM).body(Flux.interval(Duration.ofSeconds(1)).map(value -> simpleDateFormat.format(new Date())),String.class);}
}

整体来说还是比较简单的,请继续关注后期的WebFlux的学习过程~

参考文章

  • 【CSDN】(5)Spring WebFlux快速上手——响应式Spring的道法术器

  • 【IBM developerWorks】使用 Spring 5 的 WebFlux 开发反应式 Web 应用

转载于:https://www.cnblogs.com/zhoutao825638/p/10382275.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/449463.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django Rest Framework -解析器

基本代码结构 urls.py rom django.conf.urls import url, include from web.views.s5_parser import TestViewurlpatterns [url(rtest/, TestView.as_view(), nametest), ]views.py from rest_framework.views import APIView from rest_framework.response import Response f…

真格量化——菜粕策略

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np from copy import *#开始时间,用于初始化一些参数 def OnStart(context) :context.myacc = None#登录交易账号if context.accounts["回测期货"].Login…

PostgreSQL查看版本信息

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1.查看客户端版本 psql --version 1 2.查看服务器端版本 2.1 查看详细信息 select version(); 1 2.2 查看版本信息 show server_ve…

U盘版便携式Linux制作, casper-rw 解析

一直都在想&#xff0c;不管用谁的电脑&#xff0c;我都可以得到一个完全一致的工作环境&#xff0c;上面有我喜爱的软件&#xff0c;有我保存的重要资料&#xff0c;甚至浏览器的各种偏好都得一模一样&#xff01;现在的云计算技术可以部分解决这个问题&#xff0c;但是远远不…

真格量化-50ETF期权波动率策略

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np #日线级别 #开始时间,用于初始化一些参数 def OnStart(context) :print("I\m starting...")#设定一个全局变量品种,本策略交易50ETF期权g.code = Get…

canvas反向裁剪技巧

我们都知道在canvas 可以通过clip来实现剪裁功能&#xff0c;其步骤一般是先设置要裁剪的区域&#xff08;路径&#xff09;&#xff0c;然后通过ctx.clip()的实现裁剪&#xff0c;裁剪之后&#xff0c;后续的绘制只能在裁剪的区域显示效果&#xff0c;比如如下一段代码&#x…

set 和select 的区别

简单赋值是没有区别的 转载于:https://www.cnblogs.com/bingyizhihun/p/10597908.html

postgres大版本升级

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。进行升级版本之前请一定做好备份&#xff01;查看当前版本&#xff1a;[postgresnode1 ~]$ psqlpsql (9.4.4)Type "help" for h…

马上有钱:揭密25种成为有钱人的方法(图)

1、做你真正感兴趣的事—你会花很多时间在上面&#xff0c;因此你一定要感兴趣才行&#xff0c;如果不是这样的话&#xff0c;你不愿意把时间花在上面&#xff0c;就得不到成功。 2、自己当老板。为别人打工&#xff0c;你绝不会变成巨富&#xff0c;老板一心一意地缩减开支&a…

无人承运平台系统流程图

转载于:https://www.cnblogs.com/procedureMonkey/p/10598052.html

Neither the JAVA_HOME nor the JRE_HOME environment variable is defined

Centos7.5 启动tomcat报错 报错: Neither the JAVA_HOME nor the JRE_HOME environment variable is defined At least one of these environment variable is needed to run this program原因:没有安装java 解决方法:安装java yum install java -y转载于:https://www.cnblogs…

让自己变成一个上进的人

1.认真设计你的环境2.引入外部监督 求“绑架”3.获取不确定的反馈4.选择一条既细密&#xff0c;又永无止境的职业上升台阶。转载于:https://www.cnblogs.com/Julietma/p/10600241.html

年买笔记本的8个小技巧 最适合自己才最好(组图)

显然&#xff0c;智能手机和平板在一定程度上可以替代传统电脑&#xff0c;让我们可以随时随地上网、使用各种应用。不过&#xff0c;传统电脑也拥有它的不可替代性&#xff0c;比如移动办公、视频编辑、玩游戏&#xff0c;笔记本电脑可能是个更好的选择。 作为一种成熟的电脑…

MySql查询系统时间,SQLServer查询系统时间,Oracle查询系统时间

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 MySQL查询系统时间 第一种方法&#xff1a;select current_date&#xff1b; MySQL> select current_date as Systemtime; 第二…

flask同源策略解决办法及flask-cors只允许特定域名跨域

falsk 同源策略解决办法&#xff1a; 使用 flask-cors 包 并且 在代码里 加响应的一行代码解决。 from flask import Flask, session from flask_cors import CORSapp Flask(__name__) CORS(app, resources{r"/*": {"origins": "*"}}) # 允许…

基本变量和引用变量

基本数据类型作比较&#xff0c;值相等则相等&#xff0c;值不相等则不相等&#xff08;忽略数据类型&#xff09; 引用类型作比较&#xff0c;引用地址相等则相等&#xff0c;否则都是不等的。 基本数据类型&#xff0c;和引用数据类型作比较&#xff0c;是比较值是否相等&…

真格量化-持仓量第n档卖方主力跟随策略

#!/usr/bin/env python # coding:utf-8 from PoboAPI import * import datetime import time import numpy as np import pandas as pd #日线级别 #开始时间,用于初始化一些参数 def OnStart(context):print("I\m starting...")#设定一个全局变量品种,本策略交易50E…

赚大钱必备 怎样成为赚钱高手(图)

1、一旦有赚钱的念头就马上一步一个脚印去做&#xff0c;要付诸行动&#xff0c;敢于碰&#xff0c;善于磨&#xff0c;只有这样才能抓住机会。 2、想赚钱&#xff0c;就要立志当商人&#xff0c;而且目标要高&#xff0c;选定十万、二十万&#xff0c;再是一百万、五百万。 …

不定长图片验证码训练

基于LSTM和CTCLoss训练不定长图片验证码 Github项目地址&#xff1a;https://github.com/JansonJo/captcha_ocr.git # codingutf-8 """ 将三通道的图片转为灰度图进行训练 """ import itertools import os import re import random import strin…

[云框架]KONG API Gateway v1.5 -框架说明、快速部署、插件开发

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 当前版本采用KONGv0.12.3 当我们决定对应用进行微服务改造时&#xff0c;应用客户端如何与微服务交互的问题也随之而来&#xff0c;毕竟…