Reactor 中的 Mono 和 Flux:深入解析与操作符指南

部署运行你感兴趣的模型镜像

一、核心概念与区别

1. Mono(单数流)

  • 定义:表示可能包含 0个或1个 元素的异步序列

  • 特点

    • 类似 Java 的 Optional 或 Future

    • 发出一个元素后立即发出完成信号

    • 适合单值异步操作

  • 典型场景

    • 单个 HTTP 请求响应

    • 数据库查询单个记录

    • 返回单一计算结果

2. Flux(复数流)

  • 定义:表示可能包含 0到N个 元素的异步序列

  • 特点

    • 类似 Java 的 Stream 或集合

    • 可以发出多个元素后完成

    • 支持背压(backpressure)

  • 典型场景

    • 流式数据处理

    • 数据库查询多条记录

    • 实时事件流(如SSE)

二、核心操作符详解

通用操作符(Mono 和 Flux 都支持)

1. 创建操作
// 从值创建
Mono.just("Hello")
Flux.just("A", "B", "C")

// 从集合创建
Flux.fromIterable(Arrays.asList(1, 2, 3))

// 延迟创建
Mono.fromCallable(() -> expensiveOperation())
Flux.fromStream(Stream.generate(() -> random.nextInt()))
2. 转换操作
// map - 同步转换
Mono.just(5).map(x -> x * 2)  // Mono(10)
Flux.range(1,3).map(x -> x+1) // Flux(2,3,4)

// flatMap - 异步转换(1→N)
Mono.just(1).flatMap(x -> Mono.just(x * 2))  // Mono(2)
Flux.just(1,2).flatMap(x -> Flux.range(1,x)) // Flux(1,1,2)
3. 过滤操作
// filter
Flux.range(1,10).filter(x -> x%2==0)  // 2,4,6,8,10

// take/drop
Flux.range(1,10).take(3)  // 1,2,3
Flux.range(1,10).drop(7)   // 8,9,10

Mono 特有操作符

1. 默认值处理
// defaultIfEmpty
Mono.empty().defaultIfEmpty("default")  // Mono("default")

// switchIfEmpty
Mono.empty().switchIfEmpty(Mono.just("fallback"))
2. 单值特殊处理
// then - 忽略值继续执行
Mono.just(1).then(Mono.just("done"))  // Mono("done")

// thenReturn - 忽略值返回指定值
Mono.just(1).thenReturn("completed")  // Mono("completed")

Flux 特有操作符

1. 流控制
// buffer - 缓冲
Flux.range(1,5).buffer(2)  // [1,2], [3,4], [5]

// window - 窗口化
Flux.range(1,5).window(2)  // Flux(1,2), Flux(3,4), Flux(5)
2. 背压处理
// onBackpressureBuffer
Flux.range(1,1000).onBackpressureBuffer(50)

// onBackpressureDrop
Flux.range(1,1000).onBackpressureDrop()
3. 组合操作
// zipWith - 一对一组合
Flux.just("A","B").zipWith(Flux.just(1,2))
// 输出: ("A",1), ("B",2)

// mergeWith - 合并流
Flux.just(1,2).mergeWith(Flux.just(3,4))  // 1,2,3,4

三、实用代码示例

案例1:WebFlux 控制器

@GetMapping("/user/{id}")
public Mono<User> getUser(@PathVariable String id) {
    return userRepository.findById(id)
                       .switchIfEmpty(Mono.error(new UserNotFoundException()));
}

@GetMapping("/orders")
public Flux<Order> getOrders() {
    return orderRepository.findAll()
                        .filter(o -> o.getStatus() == Status.COMPLETED)
                        .take(100);
}

案例2:响应式数据处理

Flux.fromIterable(dataList)
    .window(Duration.ofSeconds(1))  // 每秒一个窗口
    .flatMap(window -> 
        window.groupBy(Data::getCategory)
             .flatMap(group -> 
                 group.reduce(new Stats(), Stats::accumulate)
             )
    )
    .subscribe(stats -> storeStats(stats));

案例3:错误处理

Mono.just(userInput)
    .map(Integer::parseInt)
    .onErrorResume(e -> {
        log.warn("Invalid input", e);
        return Mono.just(0);
    })
    .flatMap(number -> calculate(number))
    .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)));

四、选择建议

  1. 使用 Mono 当

    • 操作最多产生一个结果

    • 需要表示可能不存在的值

    • 执行不返回值的异步操作(Mono<Void>

  2. 使用 Flux 当

    • 操作可能产生多个结果

    • 处理数据流或集合

    • 需要支持背压的流式处理

五、性能考虑

  1. Mono 更轻量:适合简单场景,开销更小

  2. Flux 更强大:适合流式处理但消耗更多资源

  3. 转换成本collectList()(Flux→Mono)和 flatMapMany(Mono→Flux)都有开销

通过合理选择 Mono 和 Flux,并正确使用它们的操作符,可以构建高效、可读性强的响应式应用。

您可能感兴趣的与本文相关的镜像

FLUX.1-dev

FLUX.1-dev

图片生成
FLUX

FLUX.1-dev 是一个由 Black Forest Labs 创立的开源 AI 图像生成模型版本,它以其高质量和类似照片的真实感而闻名,并且比其他模型更有效率

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值