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

为Mono添加调用信息以优化REST服务异常处理

为Mono异常添加API路径信息的解决方案

问题背景

我们通过Spring WebFlux的Mono处理REST服务调用,当前已通过addTimeoutAndRetryToMono方法为Mono添加超时、重试和错误映射逻辑,但抛出的异常(如TimeoutException)缺少被调用服务的路径信息。路径仅在OpenAPI生成的getMonoForServiceCall方法中可用,直接传递路径因方法数量多不够优雅,尝试用contextWrite存入上下文但未在错误映射中成功获取。需在getMonoForServiceCall和addTimeoutAndRetryToMono层面修改,且getMonoForServiceCall需保持返回Mono<T>。

核心解决方案

利用Reactor的上下文(Context)存储API路径,在错误处理时读取上下文信息生成带路径的自定义异常。关键是使用onErrorMap的重载方法,该方法可同时接收异常和上下文视图(ContextView)。

修改后的代码实现

1. 在getMonoForServiceCall中存入路径到上下文

Mono<T> getMonoForServiceCall(Object param) {
    // ... 原有逻辑:准备请求参数、确定API路径等
    String apiPath = "..."; // 实际生成的API路径
    WebClient.RequestBodySpec requestBuilder = prepareRequest(webClient, apiPath, param);

    // 将路径存入Mono上下文
    return requestBuilder.retrieve().bodyToMono(returnType)
            .contextWrite(ctx -> ctx.put("api-path", apiPath));
}

2. 修改addTimeoutAndRetryToMono读取上下文并处理异常

Mono<T> addTimeoutAndRetryToMono(Mono<T> mono) {
    return mono.timeout(Duration.ofSeconds(10))
            // 使用带ContextView的onErrorMap重载方法
            .onErrorMap((throwable, contextView) -> {
                String path = contextView.getOrDefault("api-path", "未知路径");
                return handleExceptions(throwable, path);
            });
}

Throwable handleExceptions(Throwable t, String path) {
    // 根据异常类型生成带路径的自定义消息
    if (t instanceof TimeoutException) {
        return new RestClientException(String.format("调用%s时超时", path), t);
    }
    return new RestClientException(String.format("调用%s时出错:%s", path, t.getMessage()), t);
}

说明

  • 上下文(Context)是Reactor中用于传递跨操作元数据的机制,contextWrite方法会将键值对存入当前Mono的上下文,后续操作可通过ContextView读取。
  • 使用getOrDefault避免因上下文未包含路径导致的异常,默认使用"未知路径"作为兜底。
  • 异常处理时保留原始异常作为cause,便于排查根因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 13:09:54