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

使用Mutiny时onItem执行后仍触发onFailure的原因咨询

Mutiny拆分成功/失败分支时触发异常分支的问题分析

你遇到的问题核心是对Mutiny操作符的链式调用逻辑理解有误,具体是搞错了replaceWith()的作用范围。

先看你的代码:

@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Uni<RestResponse<?>> test() {
    return Uni.createFrom().item("Hello world")
        .onItem().transform(str -> {
            var resp = RestResponse.ok(str);
            System.out.println("In onItem");
            return resp;
        })
        .onFailure().recoverWithNull().replaceWith(() -> {
            System.out.println("In onFailure");
            return RestResponse.status(500);
        });
}

这里的.onFailure().recoverWithNull()确实是针对失败场景的处理,但后续的.replaceWith()并不是onFailure分支的一部分——它是作用于整个Uni的全局操作,不管前面的Uni是成功返回结果,还是经过recoverWithNull()返回null,最终都会执行replaceWith()里的逻辑,把结果替换成500响应。这就是为什么你看到In onItem打印后,In onFailure也会打印,并且Postman返回500。

要实现“成功走200,失败走500”的需求,正确的写法是用onFailure().recoverWithItem()单独处理失败分支,而非在recoverWithNull()后接replaceWith():

@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public Uni<RestResponse<?>> test() {
    return Uni.createFrom().item("Hello world")
        .onItem().transform(str -> {
            var resp = RestResponse.ok(str);
            System.out.println("In onItem");
            return resp;
        })
        .onFailure().recoverWithItem(failure -> {
            System.out.println("In onFailure");
            return RestResponse.status(500);
        });
}

修改后逻辑就正常了:

  • 当Uni成功时,只会触发onItem().transform()分支,返回200响应,不会进入失败处理逻辑
  • 当Uni真的发生失败时,才会触发onFailure().recoverWithItem()分支,返回500响应

另外补充一种写法:如果想用replaceWith()处理失败场景,需要把它放在onFailure()的分支内,效果和recoverWithItem()一致:

.onFailure().replaceWith(() -> {
    System.out.println("In onFailure");
    return RestResponse.status(500);
})

内容的提问来源于stack exchange,提问作者Gert Kommer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:15:32