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

Java中Supplier<ResponseEntity>强转RequestEntity报错如何获取请求信息

问题根因

你的强转逻辑必然抛出异常:入参request是Supplier<ResponseEntity>类型的函数式接口实例,你传入的是lambda表达式() -> restTemplate.exchange(...),和RequestEntity没有任何继承/实现关系,完全不属于同一类型体系,强转肯定失败。

解决方案

方案1:修改方法签名显式传递请求元数据(推荐,改造成本极低)

直接把你需要的URL、请求方法等信息作为入参传给executeRequest,不需要从Supplier中获取:

  1. 调整executeRequest方法逻辑:
// 方法签名新增uri、method参数,可按需新增HttpEntity等其他请求参数
protected ResponseEntity executeRequest(Supplier<ResponseEntity> request, URI uri, HttpMethod method) {
    try {
        ResponseEntity response = request.get();
        updateSessionToken(response);
        return response;
    } catch (HttpClientErrorException | HttpServerErrorException e) {
        // 直接用传入的参数拼接完整报错信息
        String msg = String.format("WDD3D-Error in service communication, 请求地址:%s, 请求方法:%s <br>错误响应:%s",
                uri.toString(), method.name(), e.getResponseBodyAsString());
        throw new MaestroException(msg);
    }
}
  1. 调整业务调用处代码:
public void execute() {
    HttpHeaders headers = buildDefaultHeaders();
    URI uri = UriBuilder.fromUri(wdd3dGatewayEndpoint + API_URL).build();
    HttpMethod method = HttpMethod.DELETE;
    HttpEntity request = new HttpEntity(headers);
    this.executeRequest(() -> restTemplate.exchange(uri, method, request, Void.class), uri, method);
}

方案2:RestTemplate拦截器全局捕获(适合调用点多的场景,无需修改业务调用代码)

如果项目中调用executeRequest的地方很多,挨个改参数成本高,可以通过RestTemplate拦截器把请求信息存入ThreadLocal,异常发生时直接读取:

  1. 定义请求上下文容器和拦截器:
// 请求信息存储容器
public class RequestContextHolder {
    private static final ThreadLocal<Map<String, String>> REQUEST_CONTEXT = new ThreadLocal<>();

    public static void set(String url, String method) {
        Map<String, String> context = new HashMap<>();
        context.put("url", url);
        context.put("method", method);
        REQUEST_CONTEXT.set(context);
    }

    public static Map<String, String> get() {
        return REQUEST_CONTEXT.get();
    }

    public static void clear() {
        REQUEST_CONTEXT.remove();
    }
}

// RestTemplate请求拦截器
public class RequestCaptureInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        RequestContextHolder.set(request.getURI().toString(), request.getMethod().name());
        try {
            return execution.execute(request, body);
        } finally {
            // 请求结束后清理,避免内存泄漏
            RequestContextHolder.clear();
        }
    }
}
  1. 给你使用的RestTemplate实例注册拦截器:
RestTemplate restTemplate = new RestTemplate();
restTemplate.setInterceptors(Collections.singletonList(new RequestCaptureInterceptor()));
  1. 调整executeRequest的异常处理逻辑即可,不需要改任何业务调用代码:
protected ResponseEntity executeRequest(Supplier<ResponseEntity> request) {
    try {
        ResponseEntity response = request.get();
        updateSessionToken(response);
        return response;
    } catch (HttpClientErrorException | HttpServerErrorException e) {
        Map<String, String> context = RequestContextHolder.get();
        String url = context != null ? context.get("url") : "未知";
        String method = context != null ? context.get("method") : "未知";
        String msg = String.format("WDD3D-Error in service communication, 请求地址:%s, 请求方法:%s <br>错误响应:%s",
                url, method, e.getResponseBodyAsString());
        throw new MaestroException(msg);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 08:06:02