You need to enable JavaScript to run this app. SpringBoot WebFlux编写泛型请求方法出现ClassCastException问题求助
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot WebFlux编写泛型请求方法出现ClassCastException问题求助

问题根因

该异常是Java泛型类型擦除机制导致的:

  • 你在泛型方法内部创建ParameterizedTypeReference<T>/ParameterizedTypeReference<V>的匿名子类时,编译阶段的泛型参数T、V已经被擦除为Object,Spring的JSON反序列化器无法获取到ViewModel这类实际类型信息,默认会将返回的JSON结构反序列化为LinkedHashMap,因此在执行lambda做类型转换时抛出类转换异常。
  • 非泛型版本可以正常运行,是因为你硬编码了ParameterizedTypeReference<Contract>和ParameterizedTypeReference<ViewModel>,具体的类型信息在编译期就保留在了匿名子类的父类泛型签名中,反序列化器可以识别到正确的目标类型。

解决方案

你只需要调整泛型方法的入参,将类型信息从调用方传入即可,有两种常用实现方式:

方案1:传入ParameterizedTypeReference(支持嵌套泛型场景)

修改方法签名,要求调用方传入请求体、响应体对应的ParameterizedTypeReference实例:

public <T, U, V> U sendRequest(String url, T contract,
                               ParameterizedTypeReference<T> contractType,
                               ParameterizedTypeReference<V> returnType,
                               Function<V, U> transform) {
    final WebClient.ResponseSpec foo = webClient.post()
            .uri(url)
            .body(Mono.just(contract), contractType)
            .retrieve();
    Mono<V> mono = foo.bodyToMono(returnType);
    final Mono<U> trans = mono.map(transform::apply);
    return trans.block();
}

调用方式:

requestRunner.sendRequest(url, contract,
        new ParameterizedTypeReference<Contract>() {},
        new ParameterizedTypeReference<ViewModel>() {},
        v -> (String)v.getResult().get("outputString"));

方案2:传入Class对象(无嵌套泛型时更简洁)

如果你的请求体、响应体都是普通类,没有List<ViewModel>这类嵌套泛型需求,可以直接传入Class对象简化调用:

public <T, U, V> U sendRequest(String url, T contract,
                               Class<T> contractClazz,
                               Class<V> returnClazz,
                               Function<V, U> transform) {
    final WebClient.ResponseSpec foo = webClient.post()
            .uri(url)
            .bodyValue(contract)
            .retrieve();
    Mono<V> mono = foo.bodyToMono(returnClazz);
    final Mono<U> trans = mono.map(transform::apply);
    return trans.block();
}

调用方式:

requestRunner.sendRequest(url, contract,
        Contract.class,
        ViewModel.class,
        v -> (String)v.getResult().get("outputString"));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 03:36:01