You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring WebFlux服务中非阻塞处理数据并返回Mono<BigDecimal>

非阻塞处理两条汇率记录并计算汇率比值

问题背景

使用collectList().block()获取Flux中的列表会触发阻塞异常,Reactor非阻塞线程禁止调用阻塞方法,需用非阻塞操作符实现汇率相除逻辑并返回Mono<BigDecimal>。

方案一:基于批量查询的非阻塞处理

利用collectList()将Flux元素收集为Mono包裹的列表,通过flatMap处理计算逻辑,同时添加校验避免数据异常:

Mono<BigDecimal> convertedRateMono = currencyRepository.findByCurrencyNameIn(List.of(from, to))
        .map(CurrencyService::fromModel)
        .collectList()
        .flatMap(currencyRates -> {
            // 校验是否获取到两条有效记录
            if (currencyRates.size() != 2) {
                return Mono.error(new IllegalArgumentException("未获取到足够的汇率记录"));
            }
            // 匹配对应货币的汇率记录(避免数据库返回顺序不一致)
            CurrencyRate fromRate = currencyRates.stream()
                    .filter(rate -> rate.getCurrencyName().equals(from))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("未找到[" + from + "]对应的汇率"));
            CurrencyRate toRate = currencyRates.stream()
                    .filter(rate -> rate.getCurrencyName().equals(to))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("未找到[" + to + "]对应的汇率"));
            // 计算汇率比值,保留3位小数并使用HALF_EVEN舍入模式
            BigDecimal convertedRate = fromRate.getRate()
                    .divide(toRate.getRate(), 3, RoundingMode.HALF_EVEN);
            return Mono.just(convertedRate);
        });

方案二:基于独立查询的合并处理

如果允许拆分查询,用Mono.zip()合并两个独立的货币查询Mono,逻辑更简洁:

Mono<BigDecimal> convertedRateMono = Mono.zip(
        // 查询源货币汇率
        currencyRepository.findByCurrencyName(from).map(CurrencyService::fromModel),
        // 查询目标货币汇率
        currencyRepository.findByCurrencyName(to).map(CurrencyService::fromModel)
)
.map(tuple -> {
    CurrencyRate fromRate = tuple.getT1();
    CurrencyRate toRate = tuple.getT2();
    return fromRate.getRate()
            .divide(toRate.getRate(), 3, RoundingMode.HALF_EVEN);
});

方案对比

  • 方案一:仅触发一次数据库批量查询,适合需要减少DB请求的场景,但需处理列表元素的匹配与校验
  • 方案二:逻辑更直观,无需处理顺序问题,但会触发两次数据库查询

内容的提问来源于stack exchange,提问作者Kris Swat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 15:30:02