带你了解Java中的Mono接口

带你了解 Java 中的 Mono 接口 🚀

在 Java 响应式编程(Reactive Programming)中,MonoProject Reactor 库的核心类型之一。它不是 Java 标准库(JDK)中的接口,而是 Reactor Core 提供的响应式类型,常与 Spring WebFlux、R2DBC 等响应式框架一起使用。

Mono 的设计灵感来源于 Reactive Streams 规范,专门用于处理 0 或 1 个元素 的异步数据流。

1. Mono 是什么?(核心定义)

  • Mono 是一个 Publisher(Reactive Streams 中的发布者接口)。
  • 它代表一个异步序列,该序列最多发出一个元素(onNext),然后以 onComplete(完成)或 onError(错误)信号终止。
  • 可以发出:
  • 0 个元素(空结果,直接完成)
  • 1 个元素(单个值)
  • 永远不会发出多个元素(与 Flux 区别)

一句话比喻

  • Mono ≈ Java 中的 Optional + CompletableFuture(异步 + 0/1 值)
  • Flux ≈ Java 中的 StreamList(0 到 N 个元素)

官方文档定义(Reactor 3.x):

A Reactive Streams Publisher with basic rx operators that emits at most one item via the onNext signal then terminates with the onComplete signal.

2. Mono 与 Flux 的区别(面试高频)

维度MonoFlux
元素数量0 或 10 到 N(可无限)
适用场景单个结果(如查询一条记录、HTTP 返回单个对象)多个结果(如查询列表、实时数据流)
类比 Java 类型Optional / CompletableFutureStream / List / Collection
常用操作符map、flatMap、then、zipWith、switchIfEmptymap、flatMap、filter、take、merge、zip
返回类型通常返回 Mono通常返回 Flux
背压支持支持(Reactive Streams 标准)支持

什么时候用 Mono?

  • 数据库单条查询(findById)
  • HTTP 接口返回单个对象
  • 异步计算单个结果(如远程调用、文件读取单值)
  • 组合多个异步操作的最终结果

3. Mono 的创建方式(常用工厂方法)

import reactor.core.publisher.Mono;
import java.time.Duration;

// 1. 创建有值的 Mono
Mono<String> mono1 = Mono.just("Hello, Reactor!");

// 2. 创建空 Mono
Mono<String> monoEmpty = Mono.empty();

// 3. 从 Supplier 创建(延迟执行)
Mono<String> monoSupplier = Mono.fromSupplier(() -> "延迟计算的值");

// 4. 从 Callable / Runnable 创建
Mono<String> monoCallable = Mono.fromCallable(() -> "从 Callable 返回");

// 5. 延迟创建(延迟指定时间)
Mono<String> delayed = Mono.delay(Duration.ofSeconds(2))
                           .map(tick -> "延迟2秒后返回");

// 6. 从 CompletableFuture 转换
Mono<String> fromFuture = Mono.fromFuture(CompletableFuture.supplyAsync(() -> "从 Future 来"));

// 7. 错误 Mono
Mono<Object> errorMono = Mono.error(new RuntimeException("出错了!"));

4. Mono 的核心操作符(Operators)

Mono 支持大量函数式操作符,实现声明式编程:

Mono<User> userMono = userRepository.findById(1L)  // 返回 Mono<User>
    .map(user -> user.getName().toUpperCase())     // 转换
    .filter(name -> name.length() > 5)             // 过滤(结果仍为 Mono)
    .flatMap(name -> fetchDetail(name))            // 扁平化嵌套 Mono
    .switchIfEmpty(Mono.just("默认用户"))          // 为空时替换
    .doOnSuccess(user -> System.out.println("成功: " + user))
    .doOnError(err -> System.err.println("错误: " + err))
    .subscribe();  // 触发执行

常用操作符分类

  • 转换mapflatMap
  • 组合zipWiththenand
  • 条件switchIfEmptydefaultIfEmpty
  • 副作用doOnNextdoOnErrordoOnSubscribe
  • 终止then()(忽略值,返回新 Mono)

5. 订阅(Subscribe)与执行

Mono 是懒执行(Lazy)的,只有调用 subscribe() 才会真正开始执行:

Mono<String> mono = Mono.just("测试");

// 方式1:简单订阅
mono.subscribe(System.out::println);

// 方式2:完整处理 onNext / onError / onComplete
mono.subscribe(
    value -> System.out.println("收到: " + value),
    error -> System.err.println("错误: " + error),
    () -> System.out.println("完成!")
);

在 Spring WebFlux 中,Controller 方法直接返回 Mono<T>Flux<T>,框架会自动订阅。

6. 实际应用场景(Spring WebFlux 示例)

@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping("/{id}")
    public Mono&lt;User> getUser(@PathVariable Long id) {
        return userService.findById(id)          // 返回 Mono&lt;User>
                         .switchIfEmpty(Mono.error(new NotFoundException("用户不存在")));
    }

    @PostMapping
    public Mono&lt;User> createUser(@RequestBody User user) {
        return userService.save(user);
    }
}

7. 与其他异步类型的转换

  • Mono.fromFuture(CompletableFuture)
  • Mono.fromCallable(...)
  • Flux.fromIterable(list).single() → 转 Mono(期望单个元素)
  • mono.as(Flux::from)flux.single()

8. 注意事项 & 最佳实践

  • 不要阻塞:Mono 内部操作应保持非阻塞(避免 block(),除非测试)。
  • 错误处理:优先使用 onErrorReturnonErrorResume 而不是 try-catch。
  • 背压:Mono 天然支持背压(下游控制上游速率)。
  • 线程模型:默认在当前线程,常用 subscribeOn / publishOn 切换调度器(Schedulers)。
  • 测试:用 StepVerifier(Reactor Test)测试 Mono/Flux。
  • 性能:响应式编程适合高并发 IO 场景,不适合纯 CPU 密集型计算。

Mono vs CompletableFuture

  • Mono:更丰富的操作符 + 声明式 + 支持背压 + 可取消。
  • CompletableFuture:更简单,但功能较少。

总结
Mono 是 Reactor 中处理单个异步结果的利器,它让异步编程变得声明式、组合式、可读性强。掌握 Mono + Flux 后,你就能轻松驾驭 Spring WebFlux、响应式微服务等现代 Java 技术栈。


想继续深入吗?
回复以下任意内容,我立刻带你继续:

  • “Mono 常用操作符 20 例详解 + 代码”
  • “Flux 完全对比详解”
  • “Spring WebFlux 中 Mono/Flux 实战项目”
  • “Mono 错误处理与重试机制”
  • “StepVerifier 测试 Mono/Flux”
  • “Reactor vs RxJava 对比”
  • “从 CompletableFuture 迁移到 Mono”

或者直接说:“给我一个完整的 Mono 入门小项目”。

有任何疑问,随时问我,我们一步步把响应式编程学透!💪

文章已创建 5130

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部