帶你了解Java中的Mono接口
在 Java 響應(yīng)式編程(Reactive Programming)中,Mono 是 Project Reactor 庫的核心類型之一。它不是 Java 標(biāo)準(zhǔn)庫(JDK)中的接口,而是 Reactor Core 提供的響應(yīng)式類型,常與 Spring WebFlux、R2DBC 等響應(yīng)式框架一起使用。
Mono 的設(shè)計靈感來源于 Reactive Streams 規(guī)范,專門用于處理 0 或 1 個元素 的異步數(shù)據(jù)流。
1. Mono 是什么?(核心定義)
- Mono 是一個 Publisher(Reactive Streams 中的發(fā)布者接口)。
- 它代表一個異步序列,該序列最多發(fā)出一個元素(onNext),然后以 onComplete(完成)或 onError(錯誤)信號終止。
- 可以發(fā)出:
- 0 個元素(空結(jié)果,直接完成)
- 1 個元素(單個值)
- 永遠(yuǎn)不會發(fā)出多個元素(與 Flux 區(qū)別)
一句話比喻:
- Mono ≈ Java 中的 Optional + CompletableFuture(異步 + 0/1 值)
- Flux ≈ Java 中的 Stream 或 List(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 的區(qū)別(面試高頻)
| 維度 | Mono | Flux |
|---|---|---|
| 元素數(shù)量 | 0 或 1 | 0 到 N(可無限) |
| 適用場景 | 單個結(jié)果(如查詢一條記錄、HTTP 返回單個對象) | 多個結(jié)果(如查詢列表、實時數(shù)據(jù)流) |
| 類比 Java 類型 | Optional / CompletableFuture | Stream / List / Collection |
| 常用操作符 | map、flatMap、then、zipWith、switchIfEmpty | map、flatMap、filter、take、merge、zip |
| 返回類型 | 通常返回 Mono | 通常返回 Flux |
| 背壓支持 | 支持(Reactive Streams 標(biāo)準(zhǔn)) | 支持 |
什么時候用 Mono?
- 數(shù)據(jù)庫單條查詢(findById)
- HTTP 接口返回單個對象
- 異步計算單個結(jié)果(如遠(yuǎn)程調(diào)用、文件讀取單值)
- 組合多個異步操作的最終結(jié)果
3. Mono 的創(chuàng)建方式(常用工廠方法)
import reactor.core.publisher.Mono;
import java.time.Duration;
// 1. 創(chuàng)建有值的 Mono
Mono<String> mono1 = Mono.just("Hello, Reactor!");
// 2. 創(chuàng)建空 Mono
Mono<String> monoEmpty = Mono.empty();
// 3. 從 Supplier 創(chuàng)建(延遲執(zhí)行)
Mono<String> monoSupplier = Mono.fromSupplier(() -> "延遲計算的值");
// 4. 從 Callable / Runnable 創(chuàng)建
Mono<String> monoCallable = Mono.fromCallable(() -> "從 Callable 返回");
// 5. 延遲創(chuàng)建(延遲指定時間)
Mono<String> delayed = Mono.delay(Duration.ofSeconds(2))
.map(tick -> "延遲2秒后返回");
// 6. 從 CompletableFuture 轉(zhuǎn)換
Mono<String> fromFuture = Mono.fromFuture(CompletableFuture.supplyAsync(() -> "從 Future 來"));
// 7. 錯誤 Mono
Mono<Object> errorMono = Mono.error(new RuntimeException("出錯了!"));4. Mono 的核心操作符(Operators)
Mono 支持大量函數(shù)式操作符,實現(xiàn)聲明式編程:
Mono<User> userMono = userRepository.findById(1L) // 返回 Mono<User>
.map(user -> user.getName().toUpperCase()) // 轉(zhuǎn)換
.filter(name -> name.length() > 5) // 過濾(結(jié)果仍為 Mono)
.flatMap(name -> fetchDetail(name)) // 扁平化嵌套 Mono
.switchIfEmpty(Mono.just("默認(rèn)用戶")) // 為空時替換
.doOnSuccess(user -> System.out.println("成功: " + user))
.doOnError(err -> System.err.println("錯誤: " + err))
.subscribe(); // 觸發(fā)執(zhí)行
常用操作符分類:
- 轉(zhuǎn)換:map、flatMap
- 組合:zipWith、then、and
- 條件:switchIfEmpty、defaultIfEmpty
- 副作用:doOnNext、doOnError、doOnSubscribe
- 終止:then()(忽略值,返回新 Mono)
5. 訂閱(Subscribe)與執(zhí)行
Mono 是懶執(zhí)行(Lazy)的,只有調(diào)用 subscribe() 才會真正開始執(zhí)行:
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. 實際應(yīng)用場景(Spring WebFlux 示例)
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public Mono<User> getUser(@PathVariable Long id) {
return userService.findById(id) // 返回 Mono<User>
.switchIfEmpty(Mono.error(new NotFoundException("用戶不存在")));
}
@PostMapping
public Mono<User> createUser(@RequestBody User user) {
return userService.save(user);
}
}
7. 與其他異步類型的轉(zhuǎn)換
- Mono.fromFuture(CompletableFuture)
- Mono.fromCallable(...)
- Flux.fromIterable(list).single() → 轉(zhuǎn) Mono(期望單個元素)
- mono.as(Flux::from) 或 flux.single()
8. 注意事項 & 最佳實踐
- 不要阻塞:Mono 內(nèi)部操作應(yīng)保持非阻塞(避免 block(),除非測試)。
- 錯誤處理:優(yōu)先使用 onErrorReturn、onErrorResume 而不是 try-catch。
- 背壓:Mono 天然支持背壓(下游控制上游速率)。
- 線程模型:默認(rèn)在當(dāng)前線程,常用 subscribeOn / publishOn 切換調(diào)度器(Schedulers)。
- 測試:用 StepVerifier(Reactor Test)測試 Mono/Flux。
- 性能:響應(yīng)式編程適合高并發(fā) IO 場景,不適合純 CPU 密集型計算。
Mono vs CompletableFuture:
- Mono:更豐富的操作符 + 聲明式 + 支持背壓 + 可取消。
- CompletableFuture:更簡單,但功能較少。
總結(jié):
Mono 是 Reactor 中處理單個異步結(jié)果的利器,它讓異步編程變得聲明式、組合式、可讀性強(qiáng)。掌握 Mono + Flux 后,你就能輕松駕馭 Spring WebFlux、響應(yīng)式微服務(wù)等現(xiàn)代 Java 技術(shù)棧。
到此這篇關(guān)于帶你了解Java中的Mono接口的文章就介紹到這了,更多相關(guān)Java Mono接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java elasticsearch使用總結(jié)與注意事項
本文系統(tǒng)梳理Java操作Elasticsearch核心流程,涵蓋環(huán)境配置、CRUD操作、搜索聚合、批量處理及安全實踐,強(qiáng)調(diào)版本適配(7.x用RestHighLevelClient,8.x+用elasticsearch-java),并提供性能優(yōu)化要點與官方文檔參考,感興趣的朋友一起看看吧2025-04-04
springCloud gateWay 統(tǒng)一鑒權(quán)的實現(xiàn)代碼
這篇文章主要介紹了springCloud gateWay 統(tǒng)一鑒權(quán)的實現(xiàn)代碼,統(tǒng)一鑒權(quán)包括鑒權(quán)邏輯和代碼實現(xiàn),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02
Java對象級別與類級別的同步鎖synchronized語法示例
這篇文章主要為大家介紹了Java對象級別與類級別的同步鎖synchronized語法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
springboot如何連接兩個數(shù)據(jù)庫(多個)
這篇文章主要介紹了springboot如何連接兩個數(shù)據(jù)庫(多個),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01

