当前位置: 首页 > news >正文

【Spring Boot】响应式编程

响应式编程

  • 1.WebFlux
  • 2.比较 MVC 和 WebFlux
    • 2.1 工作方式
    • 2.2 Spring MVC 与 Spring WebFlux 的区别
    • 2.3 使用 WebFlux 的好处
  • 3.Mono 和 Flux
    • 3.1 Mono 和 Flux 是什么
    • 3.2 Mono 和 Flux 的区别
  • 4.开发 WebFlux 的流程
    • 4.1 注解式开发流程
    • 4.2 响应式开发流程
  • 5.用注解式开发实现 Hello World
    • 5.1 配置 WebFlux 依赖
    • 5.2 编写控制器
  • 6.用响应式开发方式开发 WebFlux
    • 6.1 编写处理器类 Handler
    • 6.2 编写路由器类 Router

1.WebFlux

WebFlux 是从 Spring Framework 5.0 开始引入响应式 Web 框架的。与 Spring MVC 不同,WebFlux 不需要 ServletAPI,在完全异步且无阻塞,并通过 Reactor 项目实现 Reactive Streams 规范。

WebFlux 可以在资源有限的情况下提高 系统的吞吐量和伸缩性(不是提高性能)。这意味着在资源相同的情况下,WebFlux 可以处理更多的请求(不是业务)。

WebFlux 除支持 RESTful Web 服务外,还可以用于提供动态 HTML 内容。

2.比较 MVC 和 WebFlux

Spring MVC 采用命令式编程的方式,代码被一句一句地执行,便于开发者理解与调试代码。WebFlux 则是基于异步响应式编程。

2.1 工作方式

  • MVC:主线程接收到请求(request)→ 准备数据 → 返回数据。整个过程是单线程阻塞的,用户会感觉等待时间长是因为,在结果处理好之后才返回数据给浏览器。因此,如果请求很多,则吞吐量就上不去。
  • WebFlux:主线程接收到请求 → 立刻返回数据与的数的组合(MonoFlux,不是结果) → 开启一个新 Work 线程去做实际的数据准备工作,进行真正的业务操作 → Work 线程完成工作 → 返给用户真实数据(结果)。这种方式给人的感觉是响应时间很短,因为返回的是不变的常数,它不随用户数量的增加而变化。

2.2 Spring MVC 与 Spring WebFlux 的区别

在这里插入图片描述

对比项
Spring MVC
Spring WebFlux
地址(路由)映射@Controller、@RequestMapping 等标准的 Spring MVC 注解(1)Router Functions,提供一套函数式风格的 API,用于创建 Router、Handler 和 Filter
(2)@Controller、@RequestMapping 等标准的 Spring MVC 注解
数据流Servlet APIReactive Streams:一种支持背压(backpressure)的异步数据流处理标准,主流实现有 RxJavaReactor。Spring WebFlux 默认集成的是 Reactor
容器Tomcat、Jetty、UndertowNetty、Tomcat、Jetty、Undertow
I/O 模型同步阻塞的 I/O 模型异步非阻塞的 I/O 模型
吞吐性能
业务处理性能一样一样
支持数据库NoSQL、SQL支持 NoSQL,不支持 MySQL 等关系型数据库
请求和响应HttpServletRequestHttpServletResponseServerRequestServerResponse

2.3 使用 WebFlux 的好处

下面以餐厅 “叫号” 来比喻阻塞式开发与 WebFlux。

假设 “海底捞” 没有叫号机(前台服务员),店里有 200 个餐台供客人进餐,如果此时来了 201 个客人,那么最后一个客人就直接被拒绝服务了。

而现在有叫号机,来了 200 个客人正在用餐,后面再来 100 个客人,叫号机马上给后面的 100 个客人每人一个排队号。这样服务就不阻塞了,每个人都立马得到反馈。来再多的人也能立马给排号,但是进餐依然是阻塞的。

回到程序。我们假设,服务器最大线程资源数为 200 个,当前遇到 200个非常耗时的请求,如果再来 1 个请求时,阻塞式程序就已经处理不了(拒绝服务)了。

而对于 WebFlux,则可以做到立即响应(告诉用户等着),然后将收到的请求转发给 Work 线程去处理。WebFlux 只会对 Work 线程形成阻塞,如果再来请求也可以处理。其主要应用场景是在业务处理较耗时的场景中减少服务器资源的占用,提高并发处理速度。

对 WebFlux 的一个简单的理解就是:你来了,我立马应答你,但是服务需要等待;而不是你来了没人理你,咨询服务半天也回复不了。

结论:MVC 能满足的场景,就不需要改用 WebFlux。WebFlux 和 MVC 可以混合使用。如果开发 I/O 密集型服务,则可以选择用 WebFlux 实现。

如果在 pom.xml 文件中同时引用了 spring-boot-starter-webspring-boot-starter-webflux 依赖,则优先会使用 spring-boot-starter-web。这时,控制台输出的启动日志会提示 “Tomcat started on port(s): 8080 (http) with context path”,而使用 WebFlux 会提示 “Netty started onport(s): 8080”。

3.Mono 和 Flux

3.1 Mono 和 Flux 是什么

Mono 和 Flux 是 Reactor 中的两个基本概念。

  • Mono 和 Flux 属于 事件发布者,为消费者提供订阅接口。当有事件发生时,Mono 或 Flux 会回调消费者的相应方法,然后通知消费者相应的事件。这也是响应式编程模型。
  • Mono 和 Flux 用于处理异步数据流,它不像 MVC 中那样直接返回 String/List,而是将异步数据流包装成 Mono 或 Flux 对象。

3.2 Mono 和 Flux 的区别

  • Flux 可以发送很多 item,并且这些 item 可以经过若干算子(operators)后才被订阅。Mono 只能发送一个 item

  • Mono 主要用于返回单个数据。Flux 用于返回多个数据。如果要根据 id 查询某个 User 对象,则返回的肯定是单个 User,那么需要将其包装成 Mono<User>。若需要获取所有 User(这是一个集合),则需要将这个集合包装成 Flux<User>。这里的单个数据并不是指一个数据,而是指封装好的一个对象。多个数据就是多个对象。

  • Mono 表示包含 0 或 1 个元素的异步序列。在该序列中可以包含 3 种不同类型的消息通知:正常的包含元素的消息序列结束的消息序列出错的消息。当消息通知(正常的包含元素的消息、序列结束的消息、序列出错的消息)产生时,订阅者中有对应的方法 onNext()onComplete()onError() 被调用。

  • Flux 表示的是包含 0 到 N 个元素的异步序列,在该序列中可以包含与 Mono 相同的 3 种类型的消息通知。

  • Flux 和 Mono 之间可以进行转换。对一个 Flux 序列进行计数操作时,得到的结果是 Mono<Long> 对象。把多个 Mono 序列合并在一起,得到的是一个 Flux 对象。

4.开发 WebFlux 的流程

4.1 注解式开发流程

WebFlux 是响应式框架,其中使用的 注解式开发方式 只是 Spring 团队为了更好地迁移而提的。和 MVC 开发模式一样,地址映射也是通过 @RequestMapping 提供的,用 @Controller 或 @RestController 来代替 Handler 类。

4.2 响应式开发流程

(1)创建 Handler 类。这里的 Handler 类相当于 Spring MVC 的 Controller 层中的方法体。在响应式编程中,请求和响应不再是 HttpServletRequest 和 HttpServletResponse,而是变成了 ServerRequest 和 ServerResponse。

(2)配置 RouterFunction。RouterFunction 和注解 @RequestMapping 相似,都用于提供 URL 路径。RouterFunction 的格式也是固定的,第 1 个参数代表 路径,第 2 个参数代表 方法,合起来代表将 URL 映射到方法。

5.用注解式开发实现 Hello World

5.1 配置 WebFlux 依赖

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

5.2 编写控制器

用注解式开发 WebFlux 应用程序与 MVC 的开发方式是一样的。通过注解 @RestController 标注控制器类,通过注解 @GetMapping 指定映射路径。

package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;@RestController
public class HelloWorldController {@GetMapping("/helloworld")public Mono<String> helloworld(){return Mono.just("This is WebFlux demo");}
}

启动工程后,控制台中输出如下:

在这里插入图片描述

可以看到,WebFlux 默认使用的是 Netty 服务器,而不是 MVC 模式下的 Tomcat 服务器。

在这里插入图片描述

6.用响应式开发方式开发 WebFlux

6.1 编写处理器类 Handler

Handler 相当于 MVC 中的 Controller。用于提供实现功能的方法。

package com.example.demo;import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;@Component
public class HelloWorldHandler {public Mono<ServerResponse> sayHelloWorld(ServerRequest serverRequest) {return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(Mono.just("This is WebFlux demo"), String.class);}
}

6.2 编写路由器类 Router

package com.example.demo;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;@Configuration
public class Router {@Autowiredprivate HelloWorldHandler helloWorldHandler;@Beanpublic RouterFunction<ServerResponse> getString(){return route(GET("/helloworld"),req->helloWorldHandler.sayHelloWorld(req));}
}

上述代码中,通过 return route(GET("/helloworld"),req->helloWorldHandler.sayHelloWorld(req)); 来指定路由,包含 HTTP 方法和对应的功能方法。

在这里插入图片描述

相关文章:

【Spring Boot】响应式编程

响应式编程 1.WebFlux2.比较 MVC 和 WebFlux2.1 工作方式2.2 Spring MVC 与 Spring WebFlux 的区别2.3 使用 WebFlux 的好处 3.Mono 和 Flux3.1 Mono 和 Flux 是什么3.2 Mono 和 Flux 的区别 4.开发 WebFlux 的流程4.1 注解式开发流程4.2 响应式开发流程 5.用注解式开发实现 He…...

【C++练级之路】【Lv.21】C++11——列表初始化和声明

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、列表初始化1.1 内置类型1.2 结构体或类1.3 容器 二、声明2.1 auto2.2 decltype2.3 nullptr 三、STL的…...

输入一串字符串,前中后都有*号,去掉字符串中间和后面的*号,保留前面的*号和字母

#include <stdio.h> void fun(char* a) {//***df**fr*fg***int i 0, j 0,n0,m0;char* p;p a;while (p[i] ! \0){i;//i是一共的字符的个数}printf("%d\n",i);while (a[n] *){n;//计算字母前的*的个数}printf("%d\n", n);m n;for (j n; j < …...

【机器学习与大模型】驱动下的应用图像识别与处理

摘要&#xff1a; 本文深入探讨了机器学习在图像识别与处理领域的应用&#xff0c;特别是在大模型的推动下所取得的巨大进展。详细阐述了图像识别与处理的基本原理、关键技术&#xff0c;以及机器学习算法和大模型如何提升其性能和准确性。通过实际案例分析了其在多个领域的广泛…...

24李林跌落神坛,880还刷吗?还是换1000、900、660?

“李林今年跌落神坛了&#xff01;” “全是固定题型没新题&#xff0c;结果今年考的全是新题。” 880是“老真题的神”&#xff0c; 遇到24年&#xff0c;冷门考点多&#xff0c;计算量又大&#xff0c;就不灵了。 但“老真题”&#xff0c;还是得刷。就像往年真题是要刷的…...

数据库漫谈-sybase

sybase就是“system”加“database”&#xff0c;代表着信息系统的底层。Sybase公司很早就推出了关系数据库产品&#xff08;1987年5月推出的Sybase SQLServer1.0&#xff09;。Sybase也是第一个提出Client/Server 体系结构的思想&#xff0c;并率先在Sybase SQLServer 中实现。…...

Springboot开发 -- Postman 调试类型详解

引言 在 Spring Boot 应用开发过程中&#xff0c;接口测试是必不可少的一环。Postman 作为一款强大的 API 开发和测试工具&#xff0c;可以帮助开发者轻松构建、测试和管理 HTTP 请求。本文将为大家介绍如何在 Spring Boot 开发中使用 Postman 进行接口测试。 一、准备工作 安…...

Windows 后台启动jar并且输出日志到特定日志

Windows 后台启动jar并且输出日志到特定日志 javaw -Dfile.encodingutf-8 -jar xxx.jar >log.log 2>&1 &日志输出以年月日格式显示 javaw -Dfile.encodingutf-8 -jar xxx.jar >log_%DATE:~0,4%-%DATE:~5,2%-%DATE:~8,2%_%TIME:~0,2%-%TIME:~3,2%-%TIME:~6,2…...

垃圾回收机制及算法

文章目录 概要对象存活判断引用计数算法可达性分析算法对象是否存活各种引用 垃圾收集算法分代收集理论复制算法标记清除算法标记-整理算法 概要 垃圾收集&#xff08;Garbage Collection&#xff0c; 下文简称GC&#xff09;&#xff0c;其优缺点如下&#xff1a; 优点&#…...

蓝桥杯-暴力搜索BFS+DFS

九九乘法表挂毯 问题描述&#xff1a; 在一个古老的城堡里&#xff0c;一位名为 Alex 的少年发现了一幅巨大的九九乘法表挂毯。挂毯被划分成了9x9的方格&#xff0c;每个方格上写着相应的乘积。Alex 想象自己站在数值为1的方格上&#xff0c;他的目标是到达数值为 81 的方格。…...

巧用count与count()

在C#中&#xff0c;talentInnoPfChains.Count() 和 talentInnoPfChains.Count 的性能差异主要取决于 talentInnoPfChains 的类型。这里有两种可能的情况&#xff1a; 如果 talentInnoPfChains 是一个实现了 ICollection<T> 接口的集合&#xff08;如 List<T>, Hash…...

MongoDB 覆盖索引查询:提升性能的完整指南

MongoDB 覆盖索引查询是一种优化数据库查询性能的技术&#xff0c;它通过创建适当的索引&#xff0c;使查询可以直接从索引中获取所需的数据&#xff0c;而无需访问实际的文档数据。这种方式可以减少磁盘 I/O 和内存消耗&#xff0c;提高查询性能。 基本语法 在 MongoDB 中&a…...

ECMAScript详解

ECMAScript&#xff08;简称ES&#xff09;是一种由Ecma国际&#xff08;前身为欧洲计算机制造商协会&#xff0c;European Computer Manufacturers Association&#xff09;通过ECMA-262标准化的脚本程序设计语言。以下是对ECMAScript的详细说明&#xff1a; 1. 定义与起源 …...

如何在Windows 10上对硬盘进行碎片整理?这里提供步骤

随着时间的推移&#xff0c;由于文件系统中的碎片&#xff0c;硬盘驱动器可能会开始以较低的效率运行。为了加快驱动器的速度&#xff0c;你可以使用内置工具在Windows 10中对其进行碎片整理和优化。方法如下。 什么是碎片整理 随着时间的推移&#xff0c;组成文件的数据块&a…...

科学高效备考AMC8和AMC10竞赛,吃透2000-2024年1850道真题和解析

多做真题&#xff0c;吃透真题和背后的知识点是备考AMC8、AMC10有效的方法之一&#xff0c;通过做真题&#xff0c;可以帮助孩子找到真实竞赛的感觉&#xff0c;而且更加贴近比赛的内容&#xff0c;可以通过真题查漏补缺&#xff0c;更有针对性的补齐知识的短板。 今天我们继续…...

SQL——SELECT相关的题目

目录 197、上升的温度 577、员工奖金 586、订单最多的客户 596、超过5名学生的课 610、判断三角形 620、有趣的电影 181、超过经理收入的员工 1179、重新格式化部门表&#xff08;行转列&#xff09; 1280、学生参加各科测试的次数 1068、产品销售分析I 1075、项目员工I …...

etcd集群部署

1.etcd介绍 1.1 什么是etcd etcd的官方定义如下: A distributed, reliable key-value store for the most critical data of distributed systemetcd是一个Go语言编写的分布式、高可用的一致性键值存储系统,用于提供可靠的分布式键值(key value)存储、配置共享和服务发现等…...

VBA_MF系列技术资料1-615

MF系列VBA技术资料1-615 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…...

常用激活函数学习

常用激活函数及其应用 ReLU (Rectified Linear Unit) 公式: f ( x ) max ⁡ ( 0 , x ) f(x) \max(0, x) f(x)max(0,x)理解: 当输入值为正时&#xff0c;输出等于输入值&#xff1b;否则输出为0。ReLU函数简单且计算效率高&#xff0c;能有效缓解梯度消失问题&#xff0c;促进…...

html中被忽略的简单标签

1&#xff1a; alt的作用是在图片不能显示时的提示信息 <img src"https://img.xunfei.cn/mall/dev/ifly-mall-vip- service/business/vip/common/202404071019208761.jp" alt"提示信息" width"100px" height"100px" /> 2&#…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

Linux离线(zip方式)安装docker

目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1&#xff1a;修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本&#xff1a;CentOS 7 64位 内核版本&#xff1a;3.10.0 相关命令&#xff1a; uname -rcat /etc/os-rele…...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...

react-pdf(pdfjs-dist)如何兼容老浏览器(chrome 49)

之前都是使用react-pdf来渲染pdf文件&#xff0c;这次有个需求是要兼容xp环境&#xff0c;xp上chrome最高支持到49&#xff0c;虽然说iframe或者embed都可以实现预览pdf&#xff0c;但为了后续的定制化需求&#xff0c;还是需要使用js库来渲染。 chrome 49测试环境 能用的测试…...

零基础在实践中学习网络安全-皮卡丘靶场(第十一期-目录遍历模块)

经过前面几期的内容我们学习了很多网络安全的知识&#xff0c;而这期内容就涉及到了前面的第六期-RCE模块&#xff0c;第七期-File inclusion模块&#xff0c;第八期-Unsafe Filedownload模块。 什么是"遍历"呢&#xff1a;对学过一些开发语言的朋友来说应该知道&…...