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

在Quarkus中结合Mutiny异步使用RestClient并组合多请求结果构建自定义响应

在Quarkus中结合Mutiny异步使用RestClient并组合多请求结果构建自定义响应

嘿,刚接触响应式编程+Quarkus的话,确实需要花点时间摸透Mutiny的Uni怎么玩——我当初刚上手的时候也纠结过怎么把多个RestClient的异步请求结果拼起来,给你分享几种实用的做法,刚好匹配你的场景:

首先,先确认你已经正确注入了RestClient(Quarkus会自动处理代理,只要你加了@RestClient注解就行):

@Inject
@RestClient
MyRestClient myRestClient;

场景1:三个请求无依赖,并行执行后组合结果

这种情况是最常见的,三个接口调用互相不依赖,我们可以让它们同时跑,等所有结果都回来再组装自定义响应,效率最高:

public Uni<MyResponseType> buildCustomResponse() {
    // 先定义三个异步请求(此时还没执行,Uni是懒加载的)
    Uni<String> stringDataUni = myRestClient.getStringData();
    Uni<CustomResponseType> customDataUni = myRestClient.getCustomData();
    Uni<AnotherResponseType> anotherDataUni = myRestClient.getAnotherData();

    // 用Uni.combine把三个请求的结果组合起来
    return Uni.combine().all().unis(stringDataUni, customDataUni, anotherDataUni)
            .asTuple() // 把结果打包成Tuple,方便按顺序取
            .map(tuple -> {
                MyResponseType finalResponse = new MyResponseType();
                // 从第一个请求结果取字符串
                finalResponse.setSomeString(tuple.getItem1());
                // 从第二个请求结果里提取你需要的Integer字段
                finalResponse.setSomeInteger(tuple.getItem2().getTargetIntegerField());
                // 从第三个请求结果提取另一个Integer字段
                finalResponse.setSomeOtherInteger(tuple.getItem3().getAnotherTargetIntegerField());
                return finalResponse;
            });
}

这里的核心是Uni.combine().all().unis(),它会并行触发所有请求,只有当三个请求都成功完成后才会进入map阶段组装结果,不会有任何请求等待另一个的情况,性能拉满。

场景2:请求之间有依赖关系

如果某个请求的参数需要依赖前一个请求的结果,那我们可以用flatMap来链式处理,比如假设getCustomData()需要用到getStringData()返回的字符串当参数:

public Uni<MyResponseType> buildCustomResponseWithDependency() {
    // 先执行第一个请求,拿到结果后再触发后续请求
    return myRestClient.getStringData()
            .flatMap(stringResult -> {
                // 用第一个请求的结果作为参数发起第二个请求(这里假设接口支持传参)
                Uni<CustomResponseType> customDataUni = myRestClient.getCustomData(stringResult);
                // 第三个请求还是独立的,并行执行
                Uni<AnotherResponseType> anotherDataUni = myRestClient.getAnotherData();

                // 组合后面两个请求的结果,同时带上第一个请求的字符串
                return Uni.combine().all().unis(customDataUni, anotherDataUni)
                        .asTuple()
                        .map(tuple -> {
                            MyResponseType finalResponse = new MyResponseType();
                            finalResponse.setSomeString(stringResult);
                            finalResponse.setSomeInteger(tuple.getItem1().getTargetIntegerField());
                            finalResponse.setSomeOtherInteger(tuple.getItem2().getAnotherTargetIntegerField());
                            return finalResponse;
                        });
            });
}

flatMap的作用是把前一个Uni的结果转换成新的Uni,这样就能实现“先做A,再用A的结果做B和C”的逻辑。

额外补充:异常处理

实际开发中肯定要考虑请求失败的情况,你可以给每个Uni单独加异常处理,也可以在组合后的Uni上统一处理:

// 给单个请求加异常 fallback
Uni<String> stringDataUni = myRestClient.getStringData()
        .onFailure().recoverWithItem("默认字符串");

// 或者在组合后的结果统一处理
return Uni.combine().all().unis(stringDataUni, customDataUni, anotherDataUni)
        .asTuple()
        .map(...)
        .onFailure().recoverWithItem(failure -> {
            // 这里可以返回兜底的响应,或者抛出自定义异常
            MyResponseType fallbackResponse = new MyResponseType();
            fallbackResponse.setSomeString("兜底字符串");
            fallbackResponse.setSomeInteger(0);
            fallbackResponse.setSomeOtherInteger(0);
            return fallbackResponse;
        });

最后提个小细节:Mutiny的Uni是懒加载的,也就是说,只有当这个Uni被订阅的时候(比如你在REST接口里直接返回这个Uni,Quarkus会自动帮你订阅),所有的请求才会真正发起,不用手动触发~

备注:内容来源于stack exchange,提问作者Israel77

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 08:12:59