Flux
和 Mono
区别说明Flux
和 Mono
是 Spring WebFlux 框架中用于响应式编程的核心类型,它们都来自于 Project Reactor 库。两者的主要区别在于它们所表示的数据流的数量和完成状态。
简单来说:
Flux<T>
: 表示一个可以发出 0 个到 N 个元素的异步数据流,之后可能(也可能不)以 onComplete
信号(成功完成)或 onError
信号(发生错误)结束。Mono<T>
: 表示一个最多发出 0 个或 1 个元素的异步数据流,之后可能(也可能不)以 onComplete
或 onError
信号结束。
特性 | Flux<T> |
Mono<T> |
---|---|---|
发出元素数量 | 0 到 N 个 (多值流) | 0 或 1 个 (单值流) |
典型使用场景 | - 获取资源列表 (如 GET /users )<br>- 事件流 (如 WebSocket 消息、服务器发送事件 SSE)<br>- 批量处理结果 |
- 获取单个资源 (如 GET /users/{id} )<br>- 创建/更新/删除操作的响应 (通常返回状态或空)<br>- 认证、登录等返回单一结果的操作 |
类比 | 类似于 Stream<T> 或 List<T> ,但它是异步、非阻塞的 |
类似于 Optional<T> 或 Future<T> /CompletableFuture<T> ,但它是响应式、支持背压的 |
完成信号 | 可以发出 onComplete 或 onError |
可以发出 onComplete 或 onError |
空值表示 | 空的 Flux 表示没有元素,以 onComplete 结束。 |
空的 Mono 表示没有元素,以 onComplete 结束。可以用 Mono<Void> 表示无返回值的操作。 |
常用创建方法 | Flux.just(T...) , Flux.fromIterable(Iterable<T>) , Flux.range(start, count) , Flux.create() |
Mono.just(T) , Mono.justOrEmpty(T) , Mono.fromCallable(() -> T) , Mono.empty() , Mono.error(Throwable) |
常用转换/操作 | map , flatMap , filter , concatMap , switchMap , collectList , collectMap , zip (多个Flux) 等 |
map , flatMap , switchIfEmpty , defaultIfEmpty , thenReturn , zipWith (与另一个Mono) 等 |
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
// --- Mono 示例 ---
// 1. 发出一个值
Mono<String> singleName = Mono.just("Alice");
singleName.subscribe(name -> System.out.println("Hello, " + name)); // 输出: Hello, Alice
// 2. 可能发出一个值,也可能为空
Mono<String> possiblyEmpty = Mono.justOrEmpty(getUserNameFromDatabase()); // 如果getUserNameFromDatabase()返回null,则Mono为空
possiblyEmpty
.defaultIfEmpty("Guest") // 如果为空,则使用默认值
.subscribe(name -> System.out.println("User: " + name));
// 3. 表示一个无返回值的操作 (如保存)
Mono<Void> saveOperation = saveUserToDatabase(user);
saveOperation
.then(Mono.just("User saved successfully")) // 操作完成后,发出成功消息
.subscribe(message -> System.out.println(message));
// --- Flux 示例 ---
// 1. 发出多个值
Flux<String> names = Flux.just("Alice", "Bob", "Charlie");
names.subscribe(name -> System.out.println("Name: " + name)); // 输出三行
// 2. 从集合创建
List<String> nameList = Arrays.asList("David", "Eve", "Frank");
Flux<String> namesFromList = Flux.fromIterable(nameList);
namesFromList.subscribe(System.out::println);
// 3. 处理数据库查询返回的多条记录
Flux<User> users = userRepository.findAll(); // 假设返回Flux<User>
users
.filter(user -> user.getAge() > 18)
.map(User::getName)
.collectList() // 将所有名字收集到一个List中
.subscribe(adultNames -> System.out.println("Adults: " + adultNames));
// 4. 事件流 (概念性)
Flux<String> eventStream = getWebSocketMessageFlux(); // 持续接收消息
eventStream.subscribe(message -> System.out.println("Received: " + message));
选择 Flux
还是 Mono
主要取决于你的业务逻辑预期返回多少个元素:
Mono<T>
。这提供了更好的语义清晰度,并且可以使用 Mono
特有的操作符(如 defaultIfEmpty
, switchIfEmpty
)来优雅地处理空值情况。Flux<T>
。它提供了处理多个元素的强大操作符。在 Spring WebFlux 的 @RestController
中,你的 @GetMapping
, @PostMapping
等方法的返回类型通常就是 Mono<T>
(用于单个资源) 或 Flux<T>
(用于资源集合)。
https://blog.xqlee.com/article/2509010845002937.html