一文带你了解 Spring 5.0 WebFlux 应用场景
一、什么是 Spring WebFlux
下图截自 Spring Boot 官方网站:
结合上图,在了解 Spring WebFlux 之前,我们先来对比说说什么是 Spring MVC,这更有益我们去理解 WebFlux,图右边对 Spring MVC 的定义,原文如下:
Spring MVC is built on the Servlet API and uses a synchronous blocking I/O architecture whth a one-request-per-thread model.
翻译一下,意思如下:
Spring MVC 构建于 Servlet API 之上,使用的是同步阻塞式 I/O 模型,什么是同步阻塞式 I/O 模型呢?就是说,每一个请求对应一个线程去处理。
了解了 Spring MVC 之后,再来说说 Spring WebFlux:
上图左边,官方给出的定义如下:
Spring WebFlux is a non-blocking web framework built from the ground up to take advantage of multi-core, next-generation processors and handle massive numbers of concurrent connections.
翻译一下,内容如下:
Spring WebFlux 是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。
二、WebFlux 的优势&提升性能?
WebFlux 内部使用的是响应式编程(Reactive Programming),以 Reactor 库为基础, 基于异步和事件驱动,可以让我们在不扩充硬件资源的前提下,提升系统的吞吐量和伸缩性。
看到这里,你是不是以为 WebFlux 能够使程序运行的更快呢?量化一点,比如说我使用 WebFlux 以后,一个接口的请求响应时间是不是就缩短了呢?
抱歉了,答案是否定的!以下是官方原话:
Reactive and non-blocking generally do not make applications run faster.
WebFlux 并不能使接口的响应时间缩短,它仅仅能够提升吞吐量和伸缩性。
三、WebFlux 应用场景
上面说到了, Spring WebFlux 是一个异步非阻塞式的 Web 框架,所以,它特别适合应用在 IO 密集型的服务中,比如微服务网关这样的应用中。
PS: IO 密集型包括:磁盘IO密集型, 网络IO密集型,微服务网关就属于网络 IO 密集型,使用异步非阻塞式编程模型,能够显著地提升网关对下游服务转发的吞吐量。
四、选 WebFlux 还是 Spring MVC?
首先你需要明确一点就是:WebFlux 不是 Spring MVC 的替代方案!,虽然 WebFlux 也可以被运行在 Servlet 容器上(需是 Servlet 3.1+ 以上的容器),但是 WebFlux 主要还是应用在异步非阻塞编程模型,而 Spring MVC 是同步阻塞的,如果你目前在 Spring MVC 框架中大量使用非同步方案,那么,WebFlux 才是你想要的,否则,使用 Spring MVC 才是你的首选。
在微服务架构中,Spring MVC 和 WebFlux 可以混合使用,比如已经提到的,对于那些 IO 密集型服务(如网关),我们就可以使用 WebFlux 来实现。
选 WebFlux 还是 Spring MVC? This is not a problem!
咱不能为了装逼而装逼,为了技术而技术,还要考量到转向非阻塞响应式编程学习曲线是陡峭的,小组成员的学习成本等诸多因素。
总之一句话,在合适的场景中,选型最合适的技术。
五、异同点
从上图中,可以一眼看出 Spring MVC 和 Spring WebFlux 的相同点和不同点:
相同点:
- 都可以使用 Spring MVC 注解,如
@Controller
, 方便我们在两个 Web 框架中自由转换; - 均可以使用 Tomcat, Jetty, Undertow Servlet 容器(Servlet 3.1+);
- ...
注意点:
- Spring MVC 因为是使用的同步阻塞式,更方便开发人员编写功能代码,Debug 测试等,一般来说,如果 Spring MVC 能够满足的场景,就尽量不要用 WebFlux;
- WebFlux 默认情况下使用 Netty 作为服务器;
- WebFlux 不支持 MySql;
六、简单看看 WebFlux 是如何分发请求的
使用过 Spring MVC 的小伙伴们,应该到知道 Spring MVC 的前端控制器是 DispatcherServlet
, 而 WebFlux 是 DispatcherHandler
,它实现了 WebHandler
接口:
来看看DispatcherHandler
类中处理请求的 handle
方法:
- ①:
ServerWebExchange
对象中放置每一次 HTTP 请求响应信息,包括参数等; - ②:判断整个接口映射
mappings
集合是否为空,空则创建一个 Not Found 的错误; - ③:根据具体的请求地址获取对应的
handlerMapping
; - ④:调用具体业务方法,也就是我们定义的接口方法;
- ⑤:处理返回的结果;
七、快速入门
7.1 添加 webflux 依赖
新建一个 Spring Boot 项目,新建步骤可参考笔者另一篇博文《Spring Boot 入门教程 | 图文讲解》,在 pom.xml
文件中添加 webflux
依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
7.2 定义接口
新建一个 controller
包,用来放置对外的接口类,再创建一个 HelloWebFluxController.class
类,定义两个接口:
package site.exception.springbootwebfluxhello.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import site.exception.springbootwebfluxhello.entity.User;
/**
* @author 犬小哈 (微信号: 小哈学Java)
* @site 个人网站: www.exception.site
* @date 2019/4/15
* @time 下午9:12
* @discription
**/
@RestController
public class HelloWebFluxController {
@GetMapping("/hello")
public String hello() {
return "Hello, WebFlux !";
}
@GetMapping("/user")
public Mono<User> getUser() {
User user = new User();
user.setName("犬小哈");
user.setDesc("欢迎关注我的公众号: 小哈学Java");
return Mono.just(user);
}
}
User.java
:
package site.exception.springbootwebfluxhello.entity;
/**
* @author 犬小哈 (微信号: 小哈学Java)
* @site 个人网站: www.exception.site
* @date 2019/4/15
* @time 下午9:12
* @discription
**/
public class User {
/**
* 姓名
*/
private String name;
/**
* 描述
*/
private String desc;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
以上控制器类中,我们使用的全都是 Spring MVC 的注解,分别定义了两个接口:
- 一个 GET 请求的
/hello
接口,返回Hello, WebFlux !
字符串。 - 又定义了一个 GET 请求的
/user
方法,返回的是 JSON 格式User
对象。
这里注意,User
对象是通过 Mono
对象包装的,你可能会问,为啥不直接返回呢?
在 WebFlux 中,Mono
是非阻塞的写法,只有这样,你才能发挥 WebFlux 非阻塞 + 异步的特性。
补充:在 WebFlux 中,除了
Mono
外,还有一个Flux
,这哥俩均能充当响应式编程中发布者的角色,不同的是:
Mono
:返回 0 或 1 个元素,即单个对象。Flux
:返回 N 个元素,即 List 列表对象。
7.3 测试接口
启动项目,查看控制台输出:
当控制台中输出中包含 Netty started on port(s): 8080
语句时,说明默认使用 Netty 服务已经启动了。
打开浏览器,先对 /user
接口发起调用:
返回成功。
再来对 /user
接口测试一下:
返回 JSON 格式的 User 实体也是 OK 的!
八、总结
本文中,我们学习了什么是 Spring WebFlux, WebFlux 的优势和应用场景,接下来我么谈了谈在我们生产环境中技术选型该选 WebFlux 还是 Spring MVC, 两者之间又有什么异同点,以及从源码角度了解了 WebFlux 是如何分发请求的。
最后上手操作写了两个简单的接口,并测试成功了。
下一章中,我们将进一步学习,如何在 WebFlux 中对数据库做增删改查操作,敬请期待吧!
九、GitHub 示例代码
https://github.com/weiwosuoai/spring-boot-tutorial/tree/master/spring-boot-webflux-hello
十、Ref
- https://spring.io/
- https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html
- https://www.ibm.com/developerworks/cn/java/spring5-webflux-reactive/index.html
- https://openhome.cc/Gossip/Spring/WebFlux.html
赠送 | 面试&学习福利资源
最近在网上发现一个不错的 PDF 资源《Java 核心知识&面试.pdf》分享给大家,不光是面试,学习,你都值得拥有!!!
获取方式: 关注公众号: 小哈学Java, 后台回复 资源,既可免费无套路获取资源链接,下面是目录以及部分截图:
重要的事情说两遍,关注公众号: 小哈学Java, 后台回复 资源,既可免费无套路获取资源链接 !!!
欢迎关注微信公众号: 小哈学Java
一文带你了解 Spring 5.0 WebFlux 应用场景的更多相关文章
- 一文带你认识Spring事务
前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y Spring事务管理我相信大家都用得很多,但可能仅仅 ...
- 一文带你深入浅出Spring 事务原理
Spring事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获 ...
- 一文带你了解Spring核心接口Ordered的实现及应用
前言 最近在看框架的时候,发现了这个接口,在此进行总结,希望能够给大家帮助,同时提升自己. order接口的大体介绍 Spring框架中有这个一个接口,名字叫Ordered,联想我们在数据库中应用的O ...
- 一文带你掌握Spring Web异常处理方式
一.前言 大家好,我是 去哪里吃鱼 ,也叫小张. 最近从单位离职了,离开了五年多来朝朝夕夕皆灯火辉煌的某网,激情也好悲凉也罢,觥筹场上屡屡物是人非,调转过事业部以为能换种情绪,岂料和下了周五的班的前同 ...
- 【项目实践】一文带你搞定Spring Security + JWT
以项目驱动学习,以实践检验真知 前言 关于认证和授权,R之前已经写了两篇文章: [项目实践]在用安全框架前,我想先让你手撸一个登陆认证 [项目实践]一文带你搞定页面权限.按钮权限以及数据权限 在这两篇 ...
- JDBC、ORM、JPA、Spring Data JPA,傻傻分不清楚?一文带你厘清个中曲直,给你个选择SpringDataJPA的理由!
序言 Spring Data JPA作为Spring Data中对于关系型数据库支持的一种框架技术,属于ORM的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度. 本文档隶属于< ...
- 从源码入手,一文带你读懂Spring AOP面向切面编程
之前<零基础带你看Spring源码--IOC控制反转>详细讲了Spring容器的初始化和加载的原理,后面<你真的完全了解Java动态代理吗?看这篇就够了>介绍了下JDK的动态代 ...
- 详解 Spring 3.0 基于 Annotation 的依赖注入实现(转)
使用 @Repository.@Service.@Controller 和 @Component 将类标识为 Bean Spring 自 2.0 版本开始,陆续引入了一些注解用于简化 Spring 的 ...
- 使用spring 4.0 + maven 构建超简单的web项目
一.需求 使用spring去管理web项目,是目前非常流行的一种思路,本文将介绍使用maven+spring 4.0.2 来构建一个简单的web项目. 二.实现 1.新建一个maven项目,如下图所示 ...
随机推荐
- RDC去省赛玩前の日常训练 Chapter 1
4/3 技能点 A. 生成树的计数 论文:周冬<生成树的计数及其应用>(看不懂 pending) 一个栗子:Codeforces 719D 两个做法 Matrix-Tree + 高斯消元, ...
- HTML学习笔记8:表单
什么是表单? 一个网页表单可以将用户输入的数据发送到服务器进行处理.因为互联网用户使用复选框,单选按钮或文本字段填写表格,所以WebForms的形式类似文件或数据库.例如,WebForms ...
- JavaScript (一、ECMAScript )
一.js简介和变量 1.JavaScript的概述组成和特点 a.JavaScript 是脚本语言,是世界上最流行的编程语言,这门语言可用于 HTML 和 web,更可广泛 用于服务器.PC.笔记本电 ...
- 5月第2周业务风控关注 | 央行:严禁未经授权认可的APP接入征信系统
本文由 网易云发布. 易盾业务风控周报每周呈报值得关注的安全技术和事件,包括但不限于内容安全.移动安全.业务安全和网络安全,帮助企业提高警惕,规避这些似小实大.影响业务健康发展的安全风险. 1.央行 ...
- 杨校老师课堂之JavaScript右下角广告弹框教程
案例制作思路: 1.先制作界面 添加一个盒子包含一个按钮,使盒子绝对定位在右上角 添加一个大盒子,同理,将盒子居于左下角:其中内部包含一个顶端盒子和底部盒子 顶端盒子因为是属于大盒子内部的存在,所以宽 ...
- Netflix性能监控工具Vector
简介: Vector是Netflix开源的主机级性能监控框架,向每位工程师的浏览器提供精心挑选的高分辨率系统和应用程序指标. 登录到系统并从shell运行大量命令是一种选择,但是通常涉及的复杂性可能成 ...
- jquery 获取jquery对象的标签类型
//jquery 对象 $("#"+控件id)[0] //查看控件类型 $("#"+控件id)[0].type 实例1: < select id=&qu ...
- 微信小程序开发之formId使用(模板消息)
基于微信小程序的模板消息:基于微信的通知渠道,我们为开发者提供了可以高效触达用户的模板消息能力,以便实现服务的闭环并提供更佳的体验.模板推送位置:服务通知模板下发条件:用户本人在微信体系内与页面有交互 ...
- linux下属主目录的作用
1. /home 用户目录 系统中每一用户都有一个目录 ,被称为主目录,家目录 创建一个普通用户,系统就会在 /home 创建一个以用户为名字的目录2. /tmp 临时文件目录 系统在运行程序中产 ...
- 近期写js库中遇到的一个判别的问题
最近在写一个自己的js库,正写到数组包,在里面定义了一个排序,只对纯数字数据进行排序的方法,但是在测试的时候发现一个很诡异的问题,那就是传入一个对象的时候,它没有返回erroemsg而是返回了对象,上 ...