响应式编程WebFlux基础实战练习

什么是WebFlux?

响应式编程WebFlux是Spring Framework 5中引入的一个全新的响应式编程框架,它基于Reactor库构建,提供了异步和非阻塞的事件处理。WebFlux框架设计用于处理长时间运行的异步任务,例如网络调用或数据库操作,而不会阻塞线程。这样可以提高系统的吞吐量和伸缩性。并在Netty,Undertow和Servlet 3.1 +容器等服务器上运行。

在WebFlux中,主要的组件包括:

  • Reactor: Reactor是WebFlux底层使用的响应式编程库,提供了MonoFlux这两种响应式类型,分别用于表示0-1个和0-N个异步序列元素。
  • WebHandler: 是处理请求的核心接口,所有的请求都会被分配给一个WebHandler来处理。
  • HandlerMapping: 用于将请求映射到对应的WebHandler
  • HandlerAdapter: 用于适配WebHandler的执行,使其能够处理请求并返回响应。
  • WebFilter: 类似于Servlet中的Filter,可以在请求处理前后进行拦截和处理。
  • ServerResponseServerRequest: 分别代表HTTP的响应和请求,在WebFlux中用于处理非阻塞的请求和响应。
  • RouterFunction: 用于声明式地定义路由规则,将请求映射到处理器函数。

下面是WebFlux的基本流程图:

Request
Dispatch
Map to
Filter
Process
Response
Return
Use
Async Processing
Client
Server
HandlerMapping
WebHandler
WebFilter
HandlerAdapter
ServerResponse
Reactor

在这个流程中:

  1. 客户端发送请求到服务器。
  2. 服务器接收到请求,并将其分发给HandlerMapping
  3. HandlerMapping根据请求信息将其映射到对应的WebHandler
  4. WebFilter可以在请求到达WebHandler之前或之后进行拦截和处理。
  5. WebHandler处理请求,可能会使用Reactor库中的MonoFlux进行异步处理。
  6. HandlerAdapterWebHandler的处理结果适配成服务器可以发送的响应。
  7. ServerResponse将响应返回给客户端。

WebFlux基础实战练习

0. WebFlun环境准备

基于Spring Boot,项目依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version></parent><artifactId>chapter04-webflux</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-bom</artifactId><version>2023.0.0</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>io.projectreactor</groupId><artifactId>reactor-test</artifactId><scope>test</scope></dependency><!-- Spring Boot Starter Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.7.2</version><scope>test</scope></dependency></dependencies>
</project>

启动类

@SpringBootApplication
public class WebFluxMainApplication {public static void main(String[] args) {SpringApplication.run(WebFluxMainApplication.class,args);}
}

1. 基于注解的编程模式

WebFlux提供了两种主要的编程模式,分别是基于注解的编程模式(Annotation-based Programming)和函数式编程模式(Functional Programming)。

基于注解的编程模式(Annotation-based Programming): 这是类似于传统的Spring MVC风格的编程模式。开发者可以使用注解来定义Controller、请求映射、参数绑定等,类似于Spring MVC的@Controller和@RequestMapping注解。使用这种模式,开发者可以通过注解轻松地定义和配置应用程序的各个组件。

WebFlux基于注解的编程模式的工作流程图:
请求到达
注解映射
业务逻辑处理
响应构建
客户端请求
Controller
RequestMapping
Mono
客户端
代码示例
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;@RestController
public class WebFluxController {@GetMapping("/mono")public Mono<String> monoExample() {return Mono.just("Hello, Mono!");}@GetMapping("/flux")public Flux<Integer> fluxExample() {return Flux.just(1, 2, 3, 4, 5);}
}

测试

GET http://localhost:8080/mono 返回响应:Hello, Mono!

GET http://localhost:8080/flux 返回响应:[1,2,3,4,5]

相关API
  1. Mono

    • Mono 是 Reactor 中表示包含零个或一个元素的响应式类型。
    • 适用于表示异步操作的结果,例如从数据库查询、网络调用或其他异步任务中返回的单个结果。
    • 可以通过 Mono.just(value) 创建包含单个值的 Mono,也可以通过各种操作符对 Mono 进行组合、转换和操作。
    • Mono 可以表示一个成功的结果,也可以表示错误或空值。
  2. Flux

    • Flux 是 Reactor 中表示包含零个、一个或多个元素的响应式类型。
    • 适用于表示异步流的结果,例如从事件流、消息队列或其他异步源中返回的多个元素。
    • 可以通过 Flux.just(value1, value2, ...) 创建包含多个值的 Flux,也可以通过各种操作符对 Flux 进行处理和转换。
    • Flux 支持背压(backpressure),可以有效地处理大量的异步数据。

在使用 WebFlux 框架时,MonoFlux 通常用于表示响应的内容。Mono 表示单一值的响应,而 Flux 表示包含多个值的响应,适用于处理异步请求和构建响应式应用程序。

2. 函数式编程模式

函数式编程模式(Functional Programming): 这是WebFlux的另一种编程模式,它使用Router和Handler函数。开发者通过编写函数式的路由和处理器来定义请求的处理逻辑,而不是使用注解。这种模式更加灵活,并且适用于需要更直观、函数式风格的代码。

WebFlux基于函数式编程模式的工作流程图:
请求到达
路由
业务逻辑处理
响应构建
客户端请求
RouterFunction
HandlerFunction
ServerResponse
客户端
代码示例
@Configuration
public class WebFluxRouter {@Beanpublic RouterFunction<ServerResponse> routeExample(WebFluxHandler handler) {return route().GET("/router/mono", handler::monoExample).GET("/router/flux", handler::fluxExample).build();}
}@Component
class WebFluxHandler {public Mono<ServerResponse> monoExample(ServerRequest request) {return ok().contentType(MediaType.TEXT_PLAIN).bodyValue("Hello, Mono from Router!");}public Mono<ServerResponse> fluxExample(ServerRequest request) {return ok().contentType(MediaType.APPLICATION_JSON).body(Flux.just(1, 2, 3, 4, 5).collectList(), List.class);}}

测试

GET http://localhost:8080/router/mono 返回响应:Hello, Mono from Router!

GET http://localhost:8080/flux 返回响应:[1,2,3,4,5]

相关API
  1. RouterFunction<ServerResponse>
    • RouterFunction 是 Spring WebFlux 中用于定义路由的函数接口。
    • RouterFunction<ServerResponse> 表示这个函数定义了一组路由规则,每个路由规则都映射到一个处理器函数,用于处理特定的HTTP请求。
    • 在这个例子中,routeExample 方法创建了一个路由函数,定义了两个GET请求的路由规则,分别映射到 "/router/mono""/router/flux" 路径,并指定了相应的处理器函数。
  2. ServerRequest
    • ServerRequest 是 Spring WebFlux 中表示HTTP请求的对象。
    • 在处理器函数中,ServerRequest 包含了与请求相关的信息,例如HTTP方法、路径、请求头等。
    • 在这个例子中,monoExamplefluxExample 方法的参数中都包含了一个 ServerRequest 对象,用于处理相关的请求信息。
  3. ServerResponse
    • ServerResponse 是 Spring WebFlux 中表示HTTP响应的对象。
    • 通过 ServerResponse,可以设置响应的状态码、头部信息、内容类型等,并定义响应体。
    • 在这个例子中,monoExamplefluxExample 方法的返回类型是 Mono<ServerResponse>,表示响应是一个响应式单值。
  4. MediaType
    • MediaType 是 Spring 框架中表示媒体类型的枚举,用于指定HTTP请求和响应的媒体类型。
    • 在这个例子中,MediaType.TEXT_PLAIN 表示文本媒体类型,而 MediaType.APPLICATION_JSON 表示JSON媒体类型。
  5. MonoFlux
    • MonoFlux 是 Reactor 框架中的类型,用于处理响应式编程和异步数据流。
    • 在这个例子中,monoExample 方法返回的是一个 Mono<ServerResponse>,而 fluxExample 方法返回的是一个 Mono<ServerResponse>,表示响应是异步单值或异步数据流。
  6. .bodyValue("Hello, Mono from Router!")
    • .bodyValueServerResponse 中的方法,用于设置响应体的值。
    • 在这个例子中,通过 .bodyValue("Hello, Mono from Router!") 设置了响应体的值为字符串 “Hello, Mono from Router!”。
    • 这是一个简单的方式,适用于需要返回一个确定的值作为响应体的情况。
  7. .body(Flux.just(1, 2, 3, 4, 5).collectList(), List.class)
    • .body 方法用于设置响应体,与 .bodyValue 不同,.body 可以处理更复杂的情况,例如异步数据流。
    • 在这个例子中,使用了 .body(Flux.just(1, 2, 3, 4, 5).collectList(), List.class),表示响应体是一个包含整数 1, 2, 3, 4, 5 的 Flux,通过 collectList() 转换为 Mono<List<Integer>>
    • List.class 参数提供了响应体的元素类型信息。

这些API和注解共同构建了一个基于WebFlux的响应式路由和处理器。路由定义通过 RouterFunction 创建,处理逻辑通过 WebFluxHandler 中的方法实现,而 MonoFlux 用于表示异步的响应。

3. 异常处理和全局错误处理

代码示例
@ControllerAdvice
public class WebFluxExceptionHandler {@ExceptionHandler(Exception.class)public Mono<ServerResponse> handleException(Exception ex) {System.out.println("有错不改 ex = " + ex);return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR).body(BodyInserters.fromValue("Error: 系统繁忙!"));}
}
  • TODO:存在bug,目前拦截错误后不能正常响应"Error: 系统繁忙!"

4. WebFlux集成测试

代码示例
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebFluxIntegrationTest {@Autowiredprivate WebTestClient webTestClient;@Testvoid testMonoEndpoint() {webTestClient.get().uri("/router/mono").exchange().expectStatus().isOk().expectBody(String.class).isEqualTo("Hello, Mono from Router!");}@Testvoid testFluxEndpoint() {webTestClient.get().uri("/router/flux").exchange().expectStatus().isOk().expectBodyList(Integer.class).isEqualTo(List.of(1, 2, 3, 4, 5));}
}
相关API
  1. @SpringBootTest 注解:

    • 该注解表示这是一个Spring Boot的集成测试。
    • webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT 表示在测试过程中随机选择一个可用端口。
  2. WebTestClient 对象:

    • 通过@Autowired注入WebTestClient,这是Spring框架提供的用于进行Web请求的测试客户端。
  3. testMonoEndpoint 方法:

    • 这是一个测试方法,用于测试一个返回单一值的WebFlux端点。
    • webTestClient.get() 发起一个GET请求。
    • .uri("/router/mono") 设置请求的URI为"/router/mono"。
    • .exchange() 发送请求并获取响应。
    • .expectStatus().isOk() 验证响应的HTTP状态码是否为OK(200)。
    • .expectBody(String.class).isEqualTo("Hello, Mono from Router!") 验证响应体的内容是否为指定的字符串。
  4. testFluxEndpoint 方法:

    • 这是另一个测试方法,用于测试一个返回Flux(反应式流)的WebFlux端点。
    • testMonoEndpoint类似,不同之处在于使用了.expectBodyList(Integer.class)来验证响应体是否为一个List,并且该List的元素类型为整数。
    • 使用.isEqualTo(List.of(1, 2, 3, 4, 5))验证返回的整数列表是否与期望的一致。

总体来说,这个测试类通过WebTestClient发送HTTP请求到"/router/mono"和"/router/flux"端点,然后验证返回的响应是否符合预期。这样可以确保WebFlux端点的行为是正确的,同时也是一种测试反应式流的方式。

学习打卡day09:响应式编程WebFlux基础实战练习

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

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

相关文章

打破硬件壁垒:TVM 助力 AI技术跨平台部署

文章目录 《TVM编译器原理与实践》编辑推荐内容简介作者简介目录前言/序言获取方式 随着人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;在全世界信息产业中的广泛应用&#xff0c;深度学习模型已经成为推动AI技术革命的关键。TensorFlow、PyTorch、MX…

【习题】应用程序框架

判断题 1. 一个应用只能有一个UIAbility。错误(False) 正确(True)错误(False) 2. 创建的Empty Ability模板工程&#xff0c;初始会生成一个UIAbility文件。正确(True) 正确(True)错误(False) 3. 每调用一次router.pushUrl()方法&#xff0c;页面路由栈数量均会加1。错误(Fal…

FPGA难学在哪里,要如何学习?

难易程度&#xff0c;取决于你的专业背景 1、相关专业&#xff1a;如果你在本科学习期间&#xff0c;学习过数字电路、或者就是电子相关专业的同学。对数字电路和逻辑设计有一定基础的话&#xff0c;入门FPGA可能相对容易一些。 2、非相关专业&#xff1a;学习FPGA可能会有一定…

计算机图形学作业:三阶贝塞尔曲面

题目要求 编写程序&#xff0c;设计一个三阶的 Bezier 曲面&#xff0c;在给定控制点的情况下&#xff0c;计算出 Bezier 曲面上的点&#xff08;设 u&#xff0c;v 方向的曲面精度可通过参数设置&#xff09;&#xff0c;然后将这些点保存到数组中。如果该 Bezier 曲面以三角…

【精选】 dockerFile 使用简介 (超详细)

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【python】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 == 养成习惯(一键三连)😋 🎉欢迎关注💗一起学习👍一起讨论⭐️一起进步…

开放式耳机品牌排行榜,2024开放式耳机选购攻略

我在选后开放式耳机的路上可以说是花了不少米&#xff0c;前前后后也下了不少的功夫去做功课了解开放式耳机&#xff0c;包括市面上目前最火的西圣、南卡、cleer等热门型号我都有用过了&#xff0c;可以说是很有发言权了吧。 开放式耳机现在越来越涌现在大众的视野上了&#x…

如何构建Prompt,帮我生成QA,作为召回率检索的测试集?

最近在做搜索召回率的提升工作。粮草未动兵马先行&#xff01;在做之前应该先有一把尺子来衡量召回率的好坏。所以应该先构建测试数据集&#xff0c;然后去做标准化测试。 有了测试机集以后。再去做搜索优化&#xff0c;才能看出来效果。 当然可以选择一些开源的测试集。如果可…

POI:对Excel的基本读操作 整理2

1 简单读取操作 public class ExcelRead {String PATH "D:\\Idea-projects\\POI\\POI_projects";// 读取的一系列方法// ...... } 因为07版本和03版本操作流程大差不差&#xff0c;所以这边就以03版本为例 Testpublic void testRead03() throws IOException {//获取…

ctypes实现numpy和OpenCV Mat之间的数据交互

1、目的 将c/c编译成动态链接库&#xff0c;通过python调用&#xff0c;实现常见变量比如int&#xff0c;字符串之间的交互&#xff0c;以及np.ndarray和cv::Mat间的交互. 更简单的方式参考&#xff1a;pybind11实现numpy和OpenCV Mat的数据交互-CSDN博客 2 步骤 新建CMakeL…

运用AI搭建中间服务层(三)

CognitiveServices文件夹 在这个文件夹中&#xff0c;我们需要添加以下文件&#xff1a; IVisionService.cs 视觉服务 .cs 视觉结果.cs IEntitySearchService.cs 实体搜索服务.cs 实体结果.cs 帮助程序.cs IVisionService.cs - 访问影像服务的接口定义&#xff0c;需要…

可拖拽表单比传统表单好在哪里?

随着行业的进步和发展&#xff0c;可拖拽表单的应用价值越来越高&#xff0c;在推动企业实现流程化办公和数字化转型的过程中发挥了重要价值和作用&#xff0c;是提质增效的办公利器&#xff0c;也是众多行业客户朋友理想的合作伙伴。那么&#xff0c;可拖拽表单的优势特点表单…

【MySQL】聚合函数与分组查询

聚合函数与分组查询 一、聚合函数1、常见的聚合函数2、实例 二、分组查询1、group by子句2、准备工作3、实例4、having 条件 一、聚合函数 说明&#xff1a;聚合函数用来计算一组数据的集合并返回单个值&#xff0c;通常用这些函数完成&#xff1a;个数的统计&#xff0c;某列…

Dubbo 框架揭秘:分布式架构的精髓与魔法【一】

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Dubbo 框架揭秘&#xff1a;分布式架构的精髓与魔法【一】 前言Dubbo是什么Dubbo的核心概念整体设计 前言 在数字时代&#xff0c;分布式架构正成为应对大规模流量和复杂业务场景的标配。Dubbo&#…

vue项目使用typescript创建抽象类及其使用

如题&#xff0c;可以在vue项目使用typescript创建抽象类&#xff0c;然后使用这个抽象类。 通过TypeScript&#xff0c;可以在前端应用抽象类了。抽象类的好处&#xff0c;可以同时满足继承和多态&#xff0c;好处多多。以vue3为例&#xff1a; 1、创建抽象类 据说js类中&a…

监督学习 - XGBoost(eXtreme Gradient Boosting)

什么是机器学习 XGBoost&#xff08;eXtreme Gradient Boosting&#xff09;是一种梯度提升树算法&#xff0c;它在梯度提升框架的基础上引入了一些创新性的特性&#xff0c;以提高模型性能和训练速度。XGBoost在解决结构化数据的分类和回归问题上表现出色&#xff0c;成为许多…

Unity-游戏与帧

游戏的本质就是一个死循环 “游戏的本质就是一个死循环”这句话&#xff0c;其实是指游戏引擎的主循环。游戏引擎是游戏开发中最核心的部分&#xff0c;它负责处理玩家的输入、更新游戏状态、渲染画面等工作&#xff0c;而这些工作都是在一个不断重复的循环中完成的。 具体来…

【快刊录用】ABS一星,2区,仅2个月15天录用!

2023年12月30日-2024年1月5日 进展喜讯 经核实&#xff0c;由我处Unionpub学术推荐的论文中&#xff0c;新增2篇论文录用、3篇上线见刊、1篇数据库检索&#xff1a; 录用通知 FA20107 FA20181 — 见刊通知 FB20805 FA20269 FA20797 检索通知 FA20199 — — 计算机…

配网故障定位技术的发展与应用:保障电力供应安全稳定的重要支撑

在现代社会&#xff0c;电力供应安全稳定对于国家经济发展和民生福祉至关重要。然而&#xff0c;随着电网规模的不断扩大&#xff0c;配网故障问题也日益突出。为了确保电力供应的连续性和可靠性&#xff0c;人们不断探索和研发各种故障定位技术。本文将介绍一种基于行波测距技…

[Linux 进程(二)] Linux进程状态

文章目录 1、进程各状态的概念1.1 运行状态1.2 阻塞状态1.3 挂起状态 2、Linux进程状态2.1 运行状态 R2.2 睡眠状态 S2.3 深度睡眠 D2.4 停止状态 T2.5 僵尸状态 Z 与 死亡状态 X孤儿进程 Linux内核中&#xff0c;进程状态&#xff0c;就是PCB中的一个字段&#xff0c;是PCB中的…

2401d,ddip1027如何支持sql

原文 以下是DIP1036的SQL支持方式: 这里 auto execi(Args...)(Sqlite db, InterpolationHeader header, Args args, InterpolationFooter footer) {import arsd.sqlite;//SQLite允许你执行?1,?2等操作enum string query () {string sql;int number;import std.conv;foreach…