Spring WebFlux 零基础入门教程
1. 核心概念:什么是响应式?
在开始写代码前,我们需要转变思维。
- 传统编程 (Spring MVC):像餐厅点餐。你(线程)点完菜后必须坐在那里等,直到服务员(数据库/IO)把菜端上来。如果等待时间过长,你就无法服务其他客人。
- 响应式编程 (Spring WebFlux):像自助餐或订阅杂志。你发出请求后,不需要干等,可以去处理别的事情。当数据准备好时,系统会通知你,或者数据会像流水一样源源不断地流过来。
核心关键词:
- 非阻塞:线程不用傻等,处理完一个请求的等待时间可以去处理其他请求。
- 背压 (Backpressure):如果消费者处理数据的速度慢于生产者产生数据的速度,消费者可以通知生产者“慢点发”,防止系统崩溃。
2. 项目搭建
使用 Spring Initializr 创建项目时,只需勾选 Spring Reactive Web 依赖。
Maven 主要依赖 (pom.xml):
<dependencies>
<!-- 核心依赖:包含 Netty 服务器和 Reactor 库 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3. 核心类型:Mono 与 Flux
WebFlux 只有两个核心类,必须掌握:
| 类型 | 含义 | 形象比喻 | 示例 |
|---|---|---|---|
| Mono | 0 或 1 个元素 | 一个快递包裹 | 查询单个用户、保存操作 |
| Flux | 0 到 N 个元素 | 一条传送带 | 查询用户列表、实时股价流 |
4. 实战编码:模拟数据与接口
我们将创建一个 CounterService 来模拟业务逻辑,并在控制器中暴露接口。
第一步:编写模拟服务
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class CounterService {
// 模拟内存中的计数器
private final AtomicInteger counter = new AtomicInteger(0);
/**
* 模拟一个耗时的增加操作
* 返回 Mono,因为结果只有一个(新的计数值)
*/
public Mono<Integer> increment() {
return Mono.fromSupplier(() -> {
// 模拟业务逻辑处理耗时
try { Thread.sleep(500); } catch (Exception e) {}
return counter.incrementAndGet();
});
}
/**
* 模拟实时数据流(如股票行情)
* 返回 Flux,因为数据是源源不断的
*/
public Flux<String> getStockStream() {
return Flux.interval(Duration.ofSeconds(1)) // 每隔1秒触发一次
.map(sequence -> {
double price = 100.0 + Math.random() * 10;
return String.format("当前股价: %.2f (时间: %d秒)", price, sequence+1);
})
.map(message -> "data: " + message) // 数据格式转换(类似stream.map)
.take(10); // 仅演示:只推送10次后自动结束
}
}
第二步:编写控制器
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api")
public class DemoController {
private final CounterService counterService;
// 通过构造函数注入
public DemoController(CounterService counterService) {
this.counterService = counterService;
}
// 1. 获取当前计数 (Mono)
@PostMapping("/counter")
public Mono<Integer> getCount() {
// 注意:这里直接返回 Mono,WebFlux 会自动处理异步结果
return counterService.increment();
}
// 2. 实时数据流 (Flux) - SSE (Server-Sent Events)
// produces = MediaType.TEXT_EVENT_STREAM_VALUE 告诉浏览器这是流数据
@GetMapping(value = "/stock-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamStock() {
return counterService.getStockStream();
}
}
5. 前端交互:可视化展示
为了直观看到 Flux 的流式效果,我们写几个简单的 HTML 页面(放在 resources/static/目录下)。
- index.html - 首页用于跳转
- demo-mono.html - Mono 演示界面
- demo-flux.html - Flux 演示界面
三个页面源码如下:
6. 运行与测试
- 启动 Spring Boot 应用。
- 浏览器访问 http://localhost:8080/index.html。
- 选择对应demo页面进入
Flux Demo
点击“开始接收股价推送”按钮 进行测试数据接收
开始接收但没有结束的时候 进行点击“停止“按钮 进行测试中断数据
Mono Demo
版权所有 © 【代码谷】 欢迎非商用转载,转载请按下面格式注明出处,商业转载请联系授权,违者必究。(提示:点击下方内容复制出处)
源文: Flux 与 Mono - Spring WebFlux入门篇(一) ,链接:https://www.daimagu.com/article/2603301634032222.html,来源:代码谷
评论