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

调用Mono.block()抛出InvocationTargetException问题求助

问题分析与解决方案

1. 先揪出真实异常

InvocationTargetException只是个异常包装器,它把Mono异步流里的实际错误包在了里面。你需要在block()外层加捕获逻辑,拿到真正的问题原因:

try {
    val responseBody = webClient.get()
        .uri("/some-uri")
        .accept(MediaType.APPLICATION_JSON)
        .exchangeToMono { handleResponse(it) }
        .log()
        .block()
} catch (e: InvocationTargetException) {
    // 打印真实异常信息
    println("实际错误原因: ${e.cause?.message}")
    e.cause?.printStackTrace()
}

大概率是后续转复杂对象时反序列化失败,或者handleResponse里非2xx状态码抛出的RuntimeException被包装了。

2. 跳过String中转,直接反序列化到目标对象

既然最终要转成自定义复杂对象,没必要先转成String再手动处理——WebClient支持直接把响应体转成目标类型,既省步骤又能避免中间环节的错误:

修改响应处理函数

// 替换成你的自定义复杂对象类名
fun handleResponse(response: ClientResponse): Mono<YourComplexObject> {
    return when {
        response.statusCode().is2xxSuccessful() -> {
            // 直接将响应体转成目标对象
            response.bodyToMono(YourComplexObject::class.java)
        }
        response.statusCode().is4xxClientError() -> {
            Mono.error(RuntimeException("请求资源不存在"))
        }
        response.statusCode().is5xxServerError() -> {
            Mono.error(RuntimeException("服务端内部错误"))
        }
        else -> {
            Mono.error(RuntimeException("未知响应状态"))
        }
    }
}

简化调用代码

val complexObject = webClient.get()
    .uri("/some-uri")
    .accept(MediaType.APPLICATION_JSON)
    .exchangeToMono { handleResponse(it) }
    .log()
    .block()

3. 处理包含多态列表的复杂对象

如果你的自定义对象包含不同子类的列表(比如List<BaseType>),需要给父类配置Jackson多态注解,让框架能正确识别子类:

import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo

// 父类添加注解,指定用来区分子类的字段
@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "type" // 响应体中标识子类类型的字段名
)
@JsonSubTypes(
    JsonSubTypes.Type(value = SubTypeA::class, name = "a"),
    JsonSubTypes.Type(value = SubTypeB::class, name = "b")
)
abstract class BaseType

// 子类实现
data class SubTypeA(val fieldA: String) : BaseType()
data class SubTypeB(val fieldB: Int) : BaseType()

// 你的复杂对象结构
data class YourComplexObject(val dataList: List<BaseType>)

4. 关于"移除block()就正常"的原因

Mono是异步流,block()是同步阻塞调用,会把异步流里的异常包装成InvocationTargetException抛到主线程;而如果只是定义Mono但不调用block()/subscribe(),或者用异步订阅(subscribe(onSuccess, onError)),异常会通过onError回调处理,不会直接抛出到主线程,所以你会觉得"正常执行"。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 03:17:21