spring-webflux简介
spring-webflux是spring在5.0版本后提供的一套响应式编程风格的web开发框架。
这个框架包含了spring-framework和spring mvc,它可以运行在netty、undertow以及3.1版本以上的serlvet容器上。
你可以在项目中同时使用spring-webmvc和spring-webflux,或者只用其中一个来开发web应用。
什么是“响应式”
所谓响应式,举个例子,当调用一个api获取数据时,无需阻塞等待数据返回,而是当有数据返回时会进行告知。可见响应式是非阻塞的,意味着调用方法后,cpu可以去做别的事情,当接收到数据响应时cpu再回来处理,这种方式提高了系统的吞吐量。
而响应式编程,其实是为这种异步非阻塞的流式编程制定的一套标准。流式编程已不陌生了,java8提供的stream api就是这种风格。这套标准包括对运行环境(jvm、javascript)以及网络协议相关的规范。
spring-webflux的响应式api
spring-webflux框架是基于reactor这个开源项目开发的。reactor框架是跟spring紧密配合的。
它提供了两种api类型,分别是mono和flux;
// mono一般作用于单个对象mono person = persondao.getperson(personid);// flux一般作用于多个对象flux people = persondao.listallpeople();
尽管webflux框架基于reactor,它也能与其他的响应式框架同时使用,比如rxjava。
选择spring-webmvc还是spring-webflux呢
这两个web框架分别代表着两种不同类型的编程流派,官方给出了一个图作为对比如下
根据官方的建议有以下几点可以作为参考:
如果你已经使用了 spring-webmvc 进行开发,并且项目运行良好,就无需更改了;何况现在大多数的三方库都是阻塞的,并不能发挥出非阻塞的优势。
webflux 提供了相当多的选择;在服务层,可以使用(netty, tomcat, jetty, undertow, 和3.1版本以上的servlet容器)作为web服务;在应用层,可以选择用 @controller 定义还是使用函数编程定义;在编程风格上,可以选择用reactor、rxjava或其他。
如果你钟爱java8提供的lambda表达式这种轻量级、函数式的编程风格,那么建议选择用webflux;同时对于一些轻量级应用,或者复杂度比较低的微服务,建议使用webflux以便更好的进行控制。
在微服务架构中,可以将webmvc和webflux项目混合使用。两个框架都可以使用 @controller 这种注解的方式,使得项目的重用更加容易。
评估一个项目是否应该选择webflux的最简单的方式是,依据项目中是否会使用很多的阻塞api,比如jdbc或者一些阻塞式的api就不适用与webflux项目。
如果一个webmvc项目中有很多的外部系统调用,可以试试响应式的 webclient ,它能直接从 controller 的方法中返回响应式结果。
响应式编程的学习路线是比较陡峭的,所以如果你身在一个大型的团队中,要考虑投入的成本;不过可以用用 webclient 来体验下响应式编程。
spring-webflux不仅可以支持在tomcat、jetty以及3.1版本以上的servlet容器上,还能够运行在非servlet的服务器之上,比如netty、undertow等。
使用springboot构建一个webflux应用,默认就是使用netty,因为netty本身就是非阻塞式的实现。
并发模型
尽管webmvc和webflux都支持使用注解来定义一个controller,但是其实现方式完全不同。
webmvc是一个servlet应用,实现是阻塞式io,其维护一个线程池来处理每一个用户请求,也就是当servlet容器启动时,就会创建比如10个线程出来,因此系统吞吐量的瓶颈在于有限的连接数和阻塞的请求处理过程。
webflux可以基于netty这样的nio网络框架,它只需要很少的几个工作线程(event loop worker)就能够处理并响应请求。由于无需阻塞等待方法返回,cpu资源就得到了更好的利用。
webflux并不能让程序运行地更快;而是提高了并发处理请求的能力,即提高了系统吞吐量。
webflux代码示例
talk is cheap, show me the code
下面让我们来看一下webflux的示例,总的来说使用上是非常便捷的。
我们用springboot构建一个webflux应用非常简单,仅仅需要加入这么一个依赖
org.springframework.boot spring-boot-starter-webflux
首先定义一个对象
public class person { private integer id; private integer age; private string name;}
然后定义“personcontroller”,响应式风格中不再使用@requestmapping声明地址映射了,而是通过routerfunctions.route().get()方法
@configurationpublic class personrouter { @resource private personhandler personhandler; @bean public routerfunction personroutes() { return routerfunctions.route() .get(/person/{id}, requestpredicates.accept(mediatype.application_json), personhandler::getperson) .get(/person, requestpredicates.accept(mediatype.application_json), personhandler::listpeople) .post(/person, personhandler::createperson) .build(); }}
在personhandler中处理对应的http请求,等同于mvc架构中的service层
@componentpublic class personhandler { @resource private personrepository persondao; public mono listpeople(serverrequest request) { flux people = persondao.listallpeople(); return serverresponse.ok() .contenttype(mediatype.application_json) .body(people, person.class); } public mono createperson(serverrequest request) { mono person = request.bodytomono(person.class); return serverresponse.ok() .build(persondao.saveperson(person)); } public mono getperson(serverrequest request) { int personid = integer.parseint(request.pathvariable(id)); return persondao.getperson(personid) .flatmap(person -> serverresponse.ok().contenttype(mediatype.application_json).bodyvalue(person)) .switchifempty(serverresponse.notfound().build()); }}
通过启动日志可以证实spring-webflux是默认使用netty提供http服务
项目启动之后浏览器就能发现,你的spring-webflux项目已经正常工作了。
MAX1455 Diagnostic Clip Boost
华为MATE60是5G网络吗 华为MATE60是麒麟芯片吗
人脸识别一体机在景区管理中的应用
新岸线第三代移动芯片问世
新基建为数字化转型提供基础技术支撑,是最重要且必要的驱动力
Spring赌上未来的一击,响应式的WebFlux框架更优雅
用户与内核空间数据交换的方式之一:内核启动参数
手机通讯录丢了怎么恢复?教你如何快速找回苹果手机联系人
MPEG-2编码复用器中的FPGA逻辑设计
昕诺飞协助巴西一城市成功升级安装超过18.2万套全新LED路灯 用电成本将节省50%
冒泡排序算法原理
我国电缆行业驶入发展快车道
基于FPGA技术实现编码器脉冲的M法测速逻辑电路
NAND Flash缺货达巅峰 明年Q1 SSD价格涨幅将超10%
MAX5978 集成10位I²C系统监测器的热插拔
介绍下如何新建一个STM32寄存器版的工程
坐公交车没带零钱?带着手机就行了
中国电子:人工智能芯片和存储器技术是未来人工智能竞赛的关键
小米之家新店预热:神机K30S至尊版线下现货供应!
中国的工业机器人国产化比例由目前的27%提高到50%