步入响应式编程篇(三)之spring webFlux与R2DBC

spring webFlux与R2DBC

  • 前言
    • Spring webFlux
    • 与spring mvc的对比
      • spring mvc
      • spring webFlux
      • SSE的demo
    • R2DBC

前言

前面介绍响应式编程主要用到基于Stream API的Reactor API的方式,但如今业务操作需结合springboot,所以spring webFlux使用的更多,它是类似于spring mvc的web框架,不像springmvc的阻塞操作,一个请求通常对应一个线程,而spring webFlux响应式编程,天然支持异步+非阻塞+信号驱动;而且即使web框架用到响应式编程,但瓶颈仍然可能会出现在与关系型数据库的交互,遂引入了R2DBC等响应式方式与DB交互;

Spring webFlux

与spring mvc的对比

在这里插入图片描述
spring webFlux兼容spring mvc的,所以原来采用spring mvc开发,后面直接新引入依赖,使用spring webFlux即可;

对于响应式编程,前面两篇其实也介绍的听详细了,所以往下简单介绍它们:

spring mvc

spring mvc通常用于命令式编程,且它是阻塞的,线程接收一个请求执行的流程:浏览器 --> Controller --> Service --> Dao;
即使Tomcat中使用APR连接器接收请求,但spring mvc在处理业务时遇到阻塞业务的IO操作,该业务线程仍然需要等待;

APR利用JNI调用本地API,在NIO线程模型基础上优化的一种连接器,所以比NIO连接器性能更高,可以大幅提升Tomcat性能;

spring webFlux

而spring webFlux则默认基于Netty接收请求,是Dao(根据请求入参去数据源查询对象【数据发布者】) --> Service --> Controller --> 浏览器(相当于订阅者),而且dao查完数据推送给service时,service还可根据背压模式决定消费能力,起到异步、非阻塞发布订阅的作用;

值得一提是,spring cloud gateway的过滤器底层用的就是webflux,所以学习spring
webflux响应式编程是很有必要的;

众所周知,spring mvc处理请求时是先交由DispatcherServlet前端控制器,而spring webFlux则是交由的前端控制器为DispatcherHandler,至于后面也是交由处理器适配器、映射器等处理,只不过DispatcherHandler使用lambda更清晰:

public Mono<Void> handle(ServerWebExchange exchange) { if (this.handlerMappings == null) {return createNotFoundError();}// 跨域问题处理if (CorsUtils.isPreFlightRequest(exchange.getRequest())) {return handlePreFlight(exchange);}//拿到所有的 handlerMappingsreturn Flux.fromIterable(this.handlerMappings) // 找每一个mapping看谁能处理请求    .concatMap(mapping -> mapping.getHandler(exchange)) // 直接触发获取元素; 拿到流的第一个元素; 找到第一个能处理这个请求的handlerAdapter.next() // 如果没拿到这个元素,则响应404错误;.switchIfEmpty(createNotFoundError()) // 异常处理,一旦前面发生异常,调用处理异常.onErrorResume(ex -> handleDispatchError(exchange, ex)) // 调用方法处理请求,得到响应结果.flatMap(handler -> handleRequestWith(exchange, handler)); 
}

spring webFlux基于Reactor api的,对于api的操作翻看Reactor api篇即可;

SSE的demo

作为W3C的推荐规范,SSE在浏览器端的支持也比较广泛,而结合响应式编程,用spring webFlux实现SSE是非常契合的;

SSE 全称是 Server-Sent Events,它的作用和 WebSocket
的作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息,不同的是,WebSocket 是一种全双工通信协议,而 SSE
则是一种单工通信协议,即使用 SSE 只能服务器向浏览器推送信息流,浏览器如果向服务器发送信息,就是一个普通的 HTTP 请求。

@RequestMapping(value = "/sse",produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> sse(){System.out.println("sse入口……");return Flux.range(1,100).map(i->ServerSentEvent.builder("ha-"+i).id(i+"").comment("hello,"+i).event("haha").build()
).delayElements(Duration.ofSeconds(1));
}

如上例,每隔1s推送ServerSentEvent事件给浏览器;
在这里插入图片描述
效果如图,每隔1s,controller返回数据给浏览器;

R2DBC

要说spring webFlux是在业务处理层面异步化处理,而R2DBC则是与关系型数据库层面的异步化处理, R2DBC是 Spring 官方在 Spring5 发布了响应式 Web 框架 Spring WebFlux 之后急需能够满足异步响应的数据库交互 API,不过由于缺乏标准和驱动,Pivotal 团队开始自己研究响应式关系型数据库连接 Reactive Relational Database Connectivity,并提出了 R2DBC 规范 API 用来评估可行性并讨论数据库厂商是否有兴趣支持响应式的异步非阻塞驱动程序。最早只有 PostgreSQL 、H2、MSSQL 三家数据库厂商,不过现在 MySQL 也加入进来了,这是一个极大的利好。目前 R2DBC 的最新版本是 0.9.0.RELEASE。

官网介绍:
Spring Data R2 DBC是更大的Spring Data家族的一部分,可以轻松实现基于R2 DBC的存储库。R2DBC是Reactive Relational Database Connectivity(反应式关系数据库连接)的缩写,是一种使用反应式驱动程序集成SQL数据库的规范。Spring Data R2DBC应用了熟悉的Spring抽象和对R2DBC的存储库支持。它使得在反应式应用程序堆栈中构建使用关系数据访问技术的Spring驱动的应用程序变得更加容易。

其实spring的R2DBC也是基于Reactor api,官网使用R2DBC操作DB的例子:

ConnectionFactory connectionFactory = ConnectionFactories.get("r2dbc:h2:mem:///testdb");Mono.from(connectionFactory.create()).flatMapMany(connection -> connection.createStatement("SELECT firstname FROM PERSON WHERE age > $1").bind("$1", 42).execute()).flatMap(result -> result.map((row, rowMetadata) -> row.get("firstname", String.class))).doOnNext(System.out::println).subscribe();

而业务上使用的例子:
在这里插入图片描述

接口继承R2db2Repository,也是类似于mybatis plus的方式,userRepository作为dao,与关系型数据库交互:

在这里插入图片描述
同时R2DBC还像mybatis plus默认提供了一些api,如图笔者在接口上根本没有定义这些方法;

因spring webFlux和R2DBC都是基于reactor api,故这里只是简单列举使用例子,更多细节可以查看官网!

如有需要收藏的看官,顺便也用发财的小手点点赞哈,如有错漏,也欢迎各位在评论区评论!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

19.Word:小马-校园科技文化节❗【36】

目录 题目​ NO1.2.3 NO4.5.6 NO7.8.9 NO10.11.12索引 题目 NO1.2.3 布局→纸张大小→页边距&#xff1a;上下左右插入→封面&#xff1a;镶边→将文档开头的“黑客技术”文本移入到封面的“标题”控件中&#xff0c;删除其他控件 NO4.5.6 标题→原文原文→标题 正文→手…

redis数据安全与性能保障

数据安全与性能保障 1、持久化1.1 快照持久化1.2 AOF持久化1.3 重写/压缩AOF文件 2、复制2.1 Redis复制的启动过程2.2 主从链 3、处理系统故障3.1 验证快照文件和AOF文件 4、事务4.1 java中的redis事务使用 如有侵权&#xff0c;请联系&#xff5e; 如有错误&#xff0c;也欢迎…

【AI非常道】二零二五年一月(二),AI非常道

经常在社区看到一些非常有启发或者有收获的话语&#xff0c;但是&#xff0c;往往看过就成为过眼云烟&#xff0c;有时再想去找又找不到。索性&#xff0c;今年开始&#xff0c;看到好的言语&#xff0c;就记录下来&#xff0c;一月一发布&#xff0c;亦供大家参考。 有关AI非…

从巫师求雨说起

树上停着一只猫头鹰&#xff1a; 你相信吗&#xff1f;这不是一般的鸟&#xff0c;猫头鹰其实是一个人&#xff0c;它是一个巫师变的。 你不相信&#xff1f;那我问你&#xff0c;为什么猫头鹰和乌鸦一样&#xff0c;那叫声&#xff0c;常常让人瘆得慌&#xff1f;(owl&#x…

【C++】类和对象

面向对象编程 学习过C语言的小伙伴知道&#xff1a;C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 面向过程编程也叫结构化编程。虽然结构化编程的理念提高了程序的清晰度&#xff0c;可靠性&#xff0c…

21.3-启动流程、编码风格(了解) 第21章-FreeRTOS项目实战--基础知识之新建任务、启动流程、编码风格、系统配置 文件组成和编码风格(了解)

21.3-启动流程、编码风格(了解) 启动流程 第一种启动流程(我们就使用这个): 在main函数中将硬件初始化、RTOS系统初始化&#xff0c;同时创建所有任务&#xff0c;再启动RTOS调度器。 第二种启动流程&#xff1a; 在main函数中将硬件初始化、RTOS系统初始化&#xff0c;只…

富文本 tinyMCE Vue2 组件使用简易教程

参考官方教程 TinyMCE Vue.js integration technical reference Vue2 项目需要使用 tinyMCE Vue2 组件(tinymce/tinymce-vue)的第 3 版 安装组件 npm install --save "tinymce/tinymce-vue^3" 编写组件调用 <template><Editorref"editor"v-m…

vue框架技术相关概述以及前端框架整合

vue框架技术概述及前端框架整合 1 node.js 介绍&#xff1a;什么是node.js Node.js就是运行在服务端的JavaScript。 Node.js是一个事件驱动I/O服务端JavaScript环境&#xff0c;基于Google的V8引擎。 作用 1 运行java需要安装JDK&#xff0c;而Node.js是JavaScript的运行环…

【AI】Deepseek本地部署探索,尝试联网搜索

前言 1月下旬&#xff0c;Deepseek-R1横空出世&#xff0c;其依靠堪比GPT-o1的推理能力&#xff0c;训练成本及使用成本均只有gpt几十分之一甚至百分之一的超高性价比&#xff0c;以及它足够“OPEN”的特性直接暴打人工智能的资本行业&#xff0c;本着求实求新的精神&#xff…

DeepSeek介绍

目录 前言 1.介绍一下你自己 2.什么是CUDA CUDA的核心特点&#xff1a; CUDA的工作原理&#xff1a; CUDA的应用场景&#xff1a; CUDA的开发工具&#xff1a; CUDA的局限性&#xff1a; 3.在AI领域&#xff0c;PTX是指什么 1. PTX 的作用 2. PTX 与 AI 的关系 3. …

WGCLOUD服务器资源监控软件使用笔记 - Token is error是什么错误

[wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:90: 主机监控信息上报server开始 [wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:99: 主机监控信息上报server返回信息: {"result":"Token is error"} 这个错误是因为agent配置的wgToken和serv…

OpenAI-Edge-TTS:本地化 OpenAI 兼容的文本转语音 API,免费高效!

文本转语音&#xff08;TTS&#xff09;技术已经成为人工智能领域的重要一环&#xff0c;无论是语音助手、教育内容生成&#xff0c;还是音频文章创作&#xff0c;TTS 工具都能显著提高效率。今天要为大家介绍的是 OpenAI-Edge-TTS&#xff0c;一款基于 Microsoft Edge 在线文本…

Leetcode 131 分割回文串(纯DFS)

131. 分割回文串https://leetcode.cn/problems/palindrome-partitioning/https://leetcode.cn/problems/palindrome-partitioning/ 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 示例 1&#xff1a…

服务器虚拟化技术详解与实战:架构、部署与优化

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在现代 IT 基础架构中&#xff0c;服务器虚拟化已成为提高资源利用率、降低运维成本、提升系统灵活性的重要手段。通过服务…

记录一次,PyQT的报错,多线程Udp失效,使用工具如netstat来检查端口使用情况。

1.问题 报错Exception in thread Thread-1: Traceback (most recent call last): File "threading.py", line 932, in _bootstrap_inner File "threading.py", line 870, in run File "main.py", line 456, in udp_recv IndexError: list…

【PyTorch】6.张量运算函数:一键开启!PyTorch 张量函数的宝藏工厂

目录 1. 常见运算函数 个人主页&#xff1a;Icomi 专栏地址&#xff1a;PyTorch入门 在深度学习蓬勃发展的当下&#xff0c;PyTorch 是不可或缺的工具。它作为强大的深度学习框架&#xff0c;为构建和训练神经网络提供了高效且灵活的平台。神经网络作为人工智能的核心技术&…

线段树 算法

文章目录 基础知识适用场景小结 题目概述题目详解300.最长递增子序列2407.最长递增子序列 II 基础知识 线段树和树状数组都只是一个工具来的&#xff0c;题目并不会一下子就告诉你这个题目用到线段树和树状数组&#xff0c;这个取决于你想使用的数据结构以及所要优化的方向 线…

JVM_类的加载、链接、初始化、卸载、主动使用、被动使用

①. 说说类加载分几步&#xff1f; ①. 按照Java虚拟机规范,从class文件到加载到内存中的类,到类卸载出内存为止,它的整个生命周期包括如下7个阶段: 第一过程的加载(loading)也称为装载验证、准备、解析3个部分统称为链接(Linking)在Java中数据类型分为基本数据类型和引用数据…

SpringBoot+Vue的理解(含axios/ajax)-前后端交互前端篇

文章目录 引言SpringBootThymeleafVueSpringBootSpringBootVue&#xff08;前端&#xff09;axios/ajaxVue作用响应式动态绑定单页面应用SPA前端路由 前端路由URL和后端API URL的区别前端路由的数据从哪里来的 Vue和只用三件套axios区别 关于地址栏url和axios请求不一致VueJSPS…

socket实现HTTP请求,参考HttpURLConnection源码解析

背景 有台服务器&#xff0c;网卡绑定有2个ip地址&#xff0c;分别为&#xff1a; A&#xff1a;192.168.111.201 B&#xff1a;192.168.111.202 在这台服务器请求目标地址 C&#xff1a;192.168.111.203 时必须使用B作为源地址才能访问目标地址C&#xff0c;在这台服务器默认…