文章目录
- [一、Mono 的核心概念](#一、Mono 的核心概念)
- [二、Mono 的常见用法](#二、Mono 的常见用法)
- [三、Mono 的常见应用场景](#三、Mono 的常见应用场景)
- [四、Mono 与 Flux 的区别](#四、Mono 与 Flux 的区别)
- 五、总结
Mono 是一个常用的 单一值容器 ,它源于 响应式编程 ,特别是在 ReactiveX (即 RxJava、Project Reactor 等)框架中,常见于 Java、C#、Kotlin 等语言 。
简而言之,Mono 是 0 或 1 个值 的容器,它表示 异步操作的单个结果 。它是 Reactive Streams 的一部分,并且通常用于 异步编程 、并发处理 、流式数据处理。
一、Mono 的核心概念
1. Mono 表示一个异步值
Mono可以表示一个未来的值,它的生命周期是从没有结果到获取结果。- 它要么完成并返回一个值,要么失败。
- 它是 0 或 1 个值 ,如果有多个值或没有值,就不适合使用
Mono,而是用Flux(0 到 N 个值)处理。
例如:
- 查询数据库,成功时返回数据,失败时返回错误。
2. Mono 比 Future 更强大
在传统的 Java 编程中,我们通常会使用 Future 来表示一个异步结果,但是 Mono 和 Future 有很大的区别,特别是在 响应式流 和 操作链式组合 方面。
二、Mono 的常见用法
1. 创建一个 Mono
java
import reactor.core.publisher.Mono;
public class MonoDemo {
public static void main(String[] args) {
// 1. 从一个已知值创建 Mono
Mono<String> helloMono = Mono.just("Hello, World!");
// 2. 创建一个空的 Mono(无值)
Mono<String> emptyMono = Mono.empty();
// 3. 创建一个出错的 Mono
Mono<String> errorMono = Mono.error(new RuntimeException("Something went wrong"));
// 4. 创建一个延迟执行的 Mono
Mono<String> delayedMono = Mono.fromCallable(() -> {
Thread.sleep(1000); // 模拟延迟
return "Hello, after delay!";
});
// 5. 打印 Mono 的值(订阅)
helloMono.subscribe(value -> System.out.println("Mono Value: " + value));
emptyMono.subscribe(value -> System.out.println("Empty Mono Value: " + value),
error -> System.out.println("Error: " + error.getMessage()));
errorMono.subscribe(value -> System.out.println("This will not be printed"),
error -> System.out.println("Error: " + error.getMessage()));
delayedMono.subscribe(value -> System.out.println("Delayed Mono Value: " + value));
}
}

-
Mono.just(T):从一个已知值创建 Mono。
-
Mono.empty():创建一个空的 Mono,表示没有任何结果。
-
Mono.error(Throwable):创建一个带有错误的 Mono,表示执行失败。
-
Mono.fromCallable():创建一个延迟执行的 Mono。
2. 异步执行和 Mono 的延迟
你也可以创建一个 延迟执行的 Mono,比如从文件、数据库或外部 API 获取数据时:
java
Mono<String> delayedMono = Mono.fromCallable(() -> {
Thread.sleep(1000); // 模拟延迟
return "Hello, after delay!";
});
这个 Mono 会在触发时异步执行(例如在订阅时)。
3. 订阅 Mono 并获取值
java
mono.subscribe(value -> {
System.out.println(value); // 打印 "Hello, World!"
});
调用 subscribe() 会启动异步流。直到调用 subscribe(),Mono 才会开始执行,其他操作(例如数据库查询、文件读取)也会在这时发生。
4. 处理成功和错误
Mono 可以通过 doOnSuccess 和 doOnError 来处理不同的事件:
java
Mono.just("Hello")
.doOnSuccess(value -> System.out.println("成功获取值:" + value))
.doOnError(error -> System.err.println("发生错误:" + error.getMessage()))
.subscribe();
如果 Mono 成功,会执行 doOnSuccess,如果发生错误会执行 doOnError。
5. 错误处理
java
Mono<String> result = Mono.just("Some value")
.map(value -> {
if (value.equals("Some value")) {
throw new RuntimeException("Something went wrong!");
}
return value;
})
.onErrorReturn("Default value"); // 如果发生错误,返回默认值
result.subscribe(value -> System.out.println(value)); // 输出 "Default value"
这里的 onErrorReturn 会在发生异常时返回一个默认值。
6. 链式组合操作
Mono 允许通过链式调用进行流式组合:
java
Mono<String> result = Mono.just("Hello")
.map(String::toUpperCase) // 转成大写
.filter(value -> value.startsWith("H")) // 过滤掉不符合条件的
.defaultIfEmpty("Default Value"); // 如果为空,返回默认值
result.subscribe(value -> System.out.println(value)); // 输出 "HELLO"
map():转换值filter():过滤不符合条件的元素defaultIfEmpty():如果没有值时,使用默认值
7. 等待 Mono 完成并获取结果(阻塞方式)
虽然 Mono 是 异步 的,但是你也可以选择将其 阻塞 以获取最终结果:
java
String result = mono.block(); // 会阻塞等待直到值返回
System.out.println(result); // 输出获取到的值
注意: 阻塞操作一般不推荐在响应式流中使用,因为它违背了响应式编程的非阻塞特性。
三、Mono 的常见应用场景
1. 数据库查询
在响应式框架(如 Spring WebFlux)中,Mono 经常用于从数据库异步查询单一记录或对象。
java
public Mono<User> getUserById(String userId) {
return userRepository.findById(userId); // 假设这是一个异步查询
}
2. Web 请求响应
在 Spring WebFlux 中,Mono 可以用来表示 HTTP 响应,特别是对于异步请求。
java
@GetMapping("/user/{id}")
public Mono<User> getUser(@PathVariable String id) {
return userService.getUserById(id); // 返回 Mono<User>,表示异步的用户数据
}
四、Mono 与 Flux 的区别
Mono只表示 0 或 1 个元素,适合用于表示单一值或操作的结果。Flux表示 0 到 N 个元素,适合处理流式数据或多个值。
java
Flux<Integer> flux = Flux.just(1, 2, 3, 4, 5);
Mono<Integer> mono = Mono.just(1);
五、总结
Mono是用于表示 单一值的异步容器 ,是 响应式编程 中常用的工具。- 它可以 异步获取 、处理 或 返回一个结果。
Mono和Flux都是 Reactive Streams 的实现,帮助我们以更加高效和声明式的方式编写异步代码。