我正在尝试编写一个通用函数来执行一些 Webflux 操作,但我遇到了一个我无法弄清楚的类转换异常
* @param <T> Type of the contract
* @param <U> Return type of this method
* @param <V> Return type from the service
public <T, U, V> U sendRequest(String url, T contract, Function<V, U> transform) {
ParameterizedTypeReference<T> contractType = new ParameterizedTypeReference<T>() {};
ParameterizedTypeReference<V> returnType = new ParameterizedTypeReference<V>() {};
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(m -> transform.apply(m));
return trans.block();
}
此代码以其非通用形式正常工作。但是当我用这样的东西调用这个泛型方法时
requestRunner.<Contract, String, ViewModel>sendRequest(url, contract, v->(String)v.getResult().get("outputString"));
我得到一个例外:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.torchai.service.common.ui.ViewModel
at com.torchai.service.orchestration.service.RequestRunner.lambda$sendRequest$0(RequestRunner.java:44)
我正在运行 SpringBoot 2.4.5 版,所以我认为这不适用:https ://github.com/spring-projects/spring-framework/issues/20574
只是为了更多的上下文,在上面的示例中,ViewModel(通用类型<V>
)是服务返回其数据的格式。然后我只提取我需要的部分,在这种情况下是一个字符串(通用类型<U>
)传入的 lambda 函数从响应中获取相关字符串。但由于某种原因,Mono 没有正确映射到 ViewModel。如果我取出 map() 并返回 ViewModel,它似乎可以工作。
同样,如果我以非通用方式执行此操作,则效果很好。我可以执行 map() 步骤并正确返回一个字符串
更新
只是想明确一点,这适用于像这样的非通用版本:
public String sendRequest(String url, Contract contract, Function<ViewModel, String> transform) {
ParameterizedTypeReference<Contract> contractType = new ParameterizedTypeReference<Contract>() {};
ParameterizedTypeReference<ViewModel> returnType = new ParameterizedTypeReference<ViewModel>() {};
final WebClient.ResponseSpec foo = webClient.post()
.uri(url)
.body(Mono.just(contract), contractType)
.retrieve();
Mono<ViewModel> mono = foo.bodyToMono(returnType);
final Mono<String> trans = mono.map(m -> transform.apply(m));
return trans.block();
}
它被称为这种方式
requestRunner.<Contract, String, ViewModel>sendRequest(textExtractorUrl, cloudContract, v -> (String) v.getResult().get("outputString"));
它正确返回一个字符串,这正是我想要的通用版本