调用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
相关产品推荐
相关产品推荐

