【Spring Boot】响应式编程

news2024/11/14 15:08:39

响应式编程

  • 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 {
    @Autowired
    private HelloWorldHandler helloWorldHandler;
    @Bean
    public RouterFunction<ServerResponse> getString(){
        return route(GET("/helloworld"),req->helloWorldHandler.sayHelloWorld(req));
    }
}

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

在这里插入图片描述

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

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

相关文章

抖音小店怎么对接达人合作?五种方法分享,合作成功率超级高!

大家好&#xff0c;我是电商糖果 有很多刚开店的小店商家&#xff0c;经常会出现一个问题。 那就是不会找达人合作&#xff0c;有的朋友说是因为他社恐&#xff0c;还有的说达人不好沟通等等。 理由有很多&#xff0c;总结下来就是找达人合作这事儿太难了&#xff0c;干不了…

公安知识学习与题目练习系统

一、系统概述 系统采用C用户小程序端、管理员Web端架构。通过UniappVueSpringboot主流技术实现。具体功能分为&#xff0c;管理侧&#xff1a;可以维护学习知识点、更新知识点详情&#xff1b;C端用户&#xff1a;可以学习知识点、在线刷题练习的功能。次系统在公安专业知识学习…

【全网最全】2024电工杯数学建模A题54页A题保奖成品论文+配套代码

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 【全网最全】2024电工杯数学建模A题成品论文前三题完整解答matlabpy代码等&#xff08;后续会更新成品论文&#xff09;「首先来看看目前已有的资料&am…

【电路笔记】-巴特沃斯滤波器设计

巴特沃斯滤波器设计 文章目录 巴特沃斯滤波器设计1、概述2、Decades和Octaves3、低通巴特沃斯滤波器设计4、滤波器设计 – 巴特沃斯低通5、三阶巴特沃斯低通滤波器在之前的滤波器教程中,我们研究了简单的一阶型低通和高通滤波器,这些滤波器的 RC 滤波器电路设计中仅包含一个电…

前缀和算法:提升编程效率的秘密武器(Java版)

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人能接…

2024攻防演练利器之必修高危漏洞合集

随着网络安全的发展和攻防演练工作的推进&#xff0c;红蓝双方的技术水平皆在实践中得到了很大的提升&#xff0c;但是数字化快速发展也导致了企业的影子资产增多&#xff0c;企业很多老旧系统依旧存在历史漏洞&#xff0c;与此同时&#xff0c;在攻防演练期间&#xff0c;往往…

如何将照片从 iPhone 传输到闪存驱动器【无质量损坏】

概括 人们喜欢用 iPhone 拍照&#xff0c;因为照片通常都很漂亮&#xff0c;这都要归功于 iPhone 令人惊叹的技术。但照片更新后会占用更多空间&#xff0c;并且您可能会开始收到没有存储空间的通知。因此&#xff0c;您可以将照片传输到 USB 驱动器&#xff0c;然后从 iPhone…

脑机接口习题

9-12章习题 填空题 EEG电极分为 主动电极 和 被动电极 &#xff0c;其中 被动电极 直接与放大器连接&#xff0c; 主动电极 包含一个1~10倍的前置放大。除抗混淆滤波器&#xff0c;放大系统也包含由电阻器、电容器构成的模拟滤波器&#xff0c;把信号频率内容限制在一个特定的…

项目日记(1): boost搜索引擎

目录 1. 项目相关背景 2. 搜索引擎的相关宏原理 3. 搜索引擎的技术栈和项目环境 4. 正排索引, 倒排索引, 搜索引擎具体原理 5. 编写数据去标签化和数据清洗的模块parser(解析器). 1.项目相关背景 百度, 搜狗, 360等都有搜索引擎, 但是都是全网的搜索; boost是进行站内搜索…

Python筑基之旅-运算符

目录 一、运算符 1、了解定义 2、理解意义 2-1、基本数据处理 2-2、条件判断 2-3、逻辑操作 2-4、赋值和更新 2-5、位操作 2-6、提高代码可读性 2-7、解决实际问题 2-8、学习其他编程语言的基础 3、探索方法 3-1、理解概念 3-2、练习基本运算 3-3、掌握优先级 …

Jenkins、GitLab部署项目

1、安装JDK 1.1、下载openJdk11 yum -y install fontconfig java-11-openjdk1.2、查看安装的版本号 java -version1.3、配置环境变量 vim /etc/profile在最底部添加即可 export JAVA_HOME/usr/lib/jvm/java-11-openjdk-11.0.23.0.9-2.el7_9.x86_64 export PATH$JAVA_HOME/…

aosp14的分屏接口ISplitScreen接口获取方式更新-学员疑问答疑

背景&#xff1a; 有学员朋友在学习马哥的分屏pip自由窗口专题时候&#xff0c;做相关分屏做小桌面项目时候&#xff0c;因为原来课程版本是基于android 13进行的讲解的&#xff0c;但是现在公司已经开始逐渐进行相关的android 14的适配了&#xff0c;但是android 14这块相比a…

lspci 显示当前设备的PCI总线信息

lspci 显示当前设备的PCI总线信息 lspci 显示当前设备的PCI总线信息显示当前主机的所有PCI总线信息&#xff1a;以数字方式显示PCI厂商和设备代码同时显示数字方式还有设备代码信息以树状结构显示PCI设备的层次关系&#xff1a;更多信息 lspci 显示当前设备的PCI总线信息 lspc…

探索 Mistral 新发布的具有原生函数调用功能的 7B 模型【附notebook文件】

引言 Mistral 发布了新版的 7B 模型&#xff0c;这次更新引入了原生函数调用功能。对于开发者和 AI 爱好者来说&#xff0c;这一更新极具吸引力&#xff0c;因为它增强了模型的功能和实用性。在这篇博客中&#xff0c;我们将深入探讨这些新功能&#xff0c;展示如何使用该模型…

python表达式解析的陷阱与技巧

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;表达式的复杂性 二、案例分析&#xff1a;表达式的解读 三、陷阱揭示…

架构与思维:4大主流分布式算法介绍(图文并茂、算法拆解)

介绍 本文聚焦高并发场景下分布式一致性算法的分析和讨论 分布式场景下困扰我们的3个核心问题&#xff08;CAP&#xff09;&#xff1a;一致性、可用性、分区容错性。 1、一致性&#xff08;Consistency&#xff09;&#xff1a; 无论服务如何拆分&#xff0c;所有实例节点同一…

【安全产品】基于HFish的MySQL蜜罐溯源实验记录

MySQL蜜罐对攻击者机器任意文件读取 用HFish在3306端口部署MySQL蜜罐 配置读取文件路径 攻击者的mysql客户端版本为5.7(要求低于8.0) 之后用命令行直连 mysql -h 124.222.136.33 -P 3306 -u root -p 可以看到成功连上蜜罐的3306服务&#xff0c;但进行查询后会直接lost con…

解决CLion调试时无法显示变量值的问题

1 问题描述 使用CLion的时候&#xff0c;调试时无法显示变量的值&#xff0c;例如&#xff1a; 图来自StackOverflow。 2 解决办法 可以尝试切换调试器解决&#xff0c;在Linux下&#xff0c;CLion支持GDB和LLDB&#xff0c;如果GDB不行&#xff0c;可以切换到LLDB。 切换方…

定积分求解过程是否变限问题 以及当换元时注意事项

目录 定积分求解过程是否变限问题 文字理解&#xff1a; 实例理解&#xff1a; 易错点和易混点&#xff1a; 1&#xff1a;定积分中的换元指什么&#xff1f; 2&#xff1a; 不定积分中第一类换元法和第二类换元法的本质和区别 3&#xff1a; df(x) ----> df(x)这…

001 仿muduo库实现高性能服务器组件_项目简介

​&#x1f308;个人主页&#xff1a;Fan_558 &#x1f525; 系列专栏&#xff1a;仿muduo &#x1f339;关注我&#x1f4aa;&#x1f3fb;带你学更多知识 文章目录 一、项目简介二、所需知识储备三、什么是muduo四、Reactor模式单Reactor单线程&#xff1a;单I/O多路复⽤业务…