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

