带你了解Java中的Mono接口

 更新时间:2026年04月10日 10:04:58   作者:yingjuxia.com  
Mono是ProjectReactor库的核心类型之一,用于处理0或1个元素的异步数据流,本文主要介绍了带你了解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();  // 触发执行

常用操作符分类

  • 转换:map、flatMap
  • 组合:zipWith、then、and
  • 条件:switchIfEmpty、defaultIfEmpty
  • 副作用:doOnNext、doOnError、doOnSubscribe
  • 终止: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<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. 与其他异步类型的转换

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

8. 注意事项 & 最佳实践

  • 不要阻塞:Mono 内部操作应保持非阻塞(避免 block(),除非测试)。
  • 错误处理:优先使用 onErrorReturn、onErrorResume 而不是 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 技术栈。

到此这篇关于带你了解Java中的Mono接口的文章就介绍到这了,更多相关Java Mono接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • Java之MultipartFile和File类型互转方式

    Java之MultipartFile和File类型互转方式

    这篇文章主要介绍了Java之MultipartFile和File类型互转方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Spring Boot 项目中使用Swagger2的示例

    Spring Boot 项目中使用Swagger2的示例

    本篇文章主要介绍了Spring Boot 项目中使用Swagger2的示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-01-01
  • Java多线程编程之使用Exchanger数据交换实例

    Java多线程编程之使用Exchanger数据交换实例

    这篇文章主要介绍了Java多线程编程之使用Exchanger数据交换实例,本文直接给出实例代码,需要的朋友可以参考下
    2015-05-05
  • springboot整合minio实现文件存储功能

    springboot整合minio实现文件存储功能

    MinIO 是一个基于Apache License v2.0开源协议的对象存储服务,它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,本文给大家介绍了springboot整合minio实现文件存储功能,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-12-12
  • Java中的XML解析技术详析

    Java中的XML解析技术详析

    XML文档是一个文档树,从根部开始,并扩展到树的最底部,下面这篇文章主要给大家介绍了关于Java中XML解析技术的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-08-08
  • cmd中javac和java使用及注意事项详解

    cmd中javac和java使用及注意事项详解

    这篇文章主要介绍了cmd中javac和java使用及注意事项详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • Spring启动指定时区的两种方法

    Spring启动指定时区的两种方法

    最近项目启动,时间要修改成东七区时间,本文主要介绍了Spring启动指定时区的两种方法,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • Java集合WeakHashMap源码分析

    Java集合WeakHashMap源码分析

    这篇文章主要介绍了Java集合WeakHashMap源码分析,和HashMap一样,WeakHashMap 也是一个散列表,它存储的内容也是键值对(key-value)映射,而且键和值都可以是null,需要的朋友可以参考下
    2023-09-09
  • SpringBoot启动后立即执行的几种方法小结

    SpringBoot启动后立即执行的几种方法小结

    在项目开发中某些场景必须要用到启动项目后立即执行方式的功能,本文主要介绍了SpringBoot启动后立即执行的几种方法小结,具有一定的参考价值,感兴趣的可以了解一下
    2023-05-05
  • IntelliJ IDEA 2021.1 推出语音、视频功能,边写代码边聊天(功能超级强大)

    IntelliJ IDEA 2021.1 推出语音、视频功能,边写代码边聊天(功能超级强大

    这篇文章主要介绍了IntelliJ IDEA 2021.1 推出语音、视频功能,边写代码边聊天(功能超级强大),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04

最新评论