目录

一、什么是 Spring WebFlux

二、WebFlux 的优势&提升性能?

三、WebFlux 应用场景

四、选 WebFlux 还是 Spring MVC?

五、异同点

六、简单看看 WebFlux 是如何分发请求的

七、快速入门

  • 7.1 添加 webflux 依赖

  • 7.2 定义接口

  • 7.3 测试接口

八、总结

九、GitHub 示例代码

一、什么是 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

赠送 | 面试&学习福利资源

最近在网上发现一个不错的 PDF 资源《Java 核心面试知识.pdf》分享给大家,不光是面试,学习,你都值得拥有!!!

获取方式: 关注公众号: 小哈学Java, 后台回复 资源,既可获取资源链接,下面是目录以及部分截图:

重要的事情说两遍,获取方式: 关注公众号: 小哈学Java, 后台回复 资源,既可获取资源链接 !!!

欢迎关注微信公众号: 小哈学Java

Spring Boot 2.0 WebFlux 教程 (一) | 入门篇的更多相关文章

  1. Spring Boot 2.0 图文教程 | 集成邮件发送功能

    文章首发自个人微信公众号: 小哈学Java 个人网站: https://www.exception.site/springboot/spring-boots-send-mail 大家好,后续会间断地奉 ...

  2. 【转载】Spring boot学习记录(一)-入门篇

    前言:本系列文章非本人原创,转自:http://tengj.top/2017/04/24/springboot0/ 正文 首先声明,Spring Boot不是一门新技术.从本质上来说,Spring B ...

  3. Spring Boot学习(一):入门篇

    目录 Spring Boot简介 Spring Boot快速搭建 1 新建项目 2 运行项目 3 设置spring boot可以热部署(修改后端代码后,自动部署,不用手动部署) 3.1:配置pom.x ...

  4. 使用 Spring Boot 2.0 + WebFlux 实现 RESTful API

    概述 什么是 Spring WebFlux, 它是一种异步的, 非阻塞的, 支持背压(Back pressure)机制的Web 开发框架. 要深入了解 Spring WebFlux, 首先要了知道 R ...

  5. Spring Boot 2.x 系列教程:WebFlux 系列教程大纲(一)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! WebFlux 系列教程大纲 一.背景 大家都知道,Sprin ...

  6. Spring Boot 2.0 的快速入门(图文教程)

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! Spring Boot 2.0 的快速入门(图文教程) 大家都 ...

  7. Spring Boot 2.x 系列教程:WebFlux REST API 全局异常处理 Error Handling

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 本文内容 为什么要全局异常处理? WebFlux REST 全 ...

  8. Spring Boot 2.0 配置图文教程

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 本章内容 自定义属性快速入门 外化配置 自动配置 自定义创建 ...

  9. Spring Boot 2.x基础教程:事务管理入门

    什么是事务? 我们在开发企业应用时,通常业务人员的一个操作实际上是对数据库读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻 ...

随机推荐

  1. ubuntu 命令整合1

    一.linux命令基本格式 命令名[选项] [参数] 注意: 命令名区分字母大小写 命令名必须有 选项.参数可以没有,选项一般使用减号开头二.具体Linux命令 1.who 显示登录系统中的用户的信息 ...

  2. UUID那些事

    UUID那些事 UUID 是一个全局唯一的通用识别码.它使用某种规则,而不是某种中心化的自增方式,来保证这个识别码的全局唯一性.UUID 有非常多的使用场景,比如在分布式系统中,需要生成全局唯一 ID ...

  3. Vue.js——60分钟组件快速入门

    一.组件简介 组件系统是Vue.js其中一个重要的概念,它提供了一种抽象,让我们可以使用独立可复用的小组件来构建大型应用,任意类型的应用界面都可以抽象为一个组件树: 那么什么是组件呢?组件可以扩展HT ...

  4. springboot数据库连接池使用策略

    springboot官方文档介绍数据库连接池的使用策略如下: Production database connections can also be auto-configured using a p ...

  5. Hibernate中的持久化类

    一.持久化类概述 就是一个JavaBean,这个JavaBean与表建立了映射关系.这个类就称为是持久化类. 简单理解为 持久化类=JavaBean+映射文件. 持久化类:是指其实例需要被Hibern ...

  6. 深夜学算法之SkipList:让链表飞

    1. 前言 上次写Python操作LevelDB时提到过,有机会要实现下SkipList.摘录下wiki介绍: 跳跃列表是一种随机化数据结构,基于并联的链表,其效率可比拟二叉查找树. 我们知道对于有序 ...

  7. 20.QT-Qpixmap实现图片鼠标缩放,鼠标拖动示例(详解)

    通过 QPainter 绘画实现,以本地图片985*740为例 如下图所示: 效果如下所示: 实现原理 主要通过以下函数实现: , ); //平铺显示pixmap //x y w h :表示绘画区域 ...

  8. CS224n笔记0

    我准备跟随码农场hankcs大神的脚步,学习一下斯坦福的CS224n课程. 关于该课程的简介,hankcs大神已经写得很清楚了.

  9. spring boot actuator专题

    spring-boot-starter-actuator模块的实现对于实施微服务的中小团队来说,可以有效地减少监控系统在采集应用指标时的开发量.当然,它也并不是万能的,有时候我们也需要对其做一些简单的 ...

  10. bootgrid

    编写bootgrid前提条件  有关bootgrid的.css和.js库文件 参数:ajax:   必须设置为true  post:   传递给Java的参数  url:   与java连接的方法名  ...