- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试编写一个通用函数来执行一些 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"));
我得到一个异常(exception):
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)
我正在运行 2.4.5 版的 SpringBoot,所以我认为这不适用: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"));
它正确地返回了一个字符串,这正是我想要的通用版本
最佳答案
我能够在本地重现此问题并开始进行一些调试,但真的很难看出 webflux 代码中发生了什么/哪里发生了什么。
类型声明ViewModel
对于 V
仅在调用者处已知,但在方法中未知 sendRequest
.好像是用了ParameterizedTypeReference<V>
是问题所在。在这种情况下 V
只是真实类型的通用占位符,所以 spring 只捕获 V
在ParameterizedTypeReference
并且不知道应该将响应反序列化为 ViewModel
的实例.相反,它会尝试为 V
类型找到反序列化器。它能找到的最接近的类型是 LinkedHashMap
.因此,在您的情况下,您最终获得了顶级 LinkedHashMap
(而不是 ViewModel
)包含一个键 result
值类型为 LinkedHashMap
其中包含您的结果条目。这就是为什么你得到 ClassCastException
.
我已经删除了 ParameterizedTypeReference<V>
并使用显式 Class<V>
版本而不是它的工作原理。使用此版本,您不必自己放入泛型类型,只需向方法提供参数,泛型就会自动从上下文中派生。
public <T, U, V> U sendRequest(String url, T contract, Class<V> responseType, Function<V, U> transform)
{
WebClient.ResponseSpec foo = webClient.post()
.uri(url)
.body(Mono.just(contract), contract.getClass())
.retrieve();
Mono<V> mono = foo.bodyToMono(responseType);
Mono<U> trans = mono.map(transform);
return trans.block();
}
调用:
requestRunner.sendRequest(url, contract, ViewModel.class, v -> (String) v.getResult().get("outputString"));
如果有人想进行更深入的调查,这是我最小的可重现示例。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
DemoApplication.java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Controller .java
@RestController
public class Controller
{
private static class ViewModel
{
private LinkedHashMap<String, Object> result = new LinkedHashMap<>();
public LinkedHashMap<String, Object> getResult()
{
return result;
}
public void setResult(LinkedHashMap<String, Object> result)
{
this.result = result;
}
}
@PostMapping("/fetchViewModel")
public ViewModel fetchViewModel()
{
ViewModel result = new ViewModel();
result.getResult().put("outputString", "value");
return result;
}
@GetMapping("/start")
public Mono<String> startSuccess()
{
return this.sendRequest("fetchViewModel", "contract", ViewModel.class, v -> (String) v.getResult().get("outputString"));
}
private <T, U, V> Mono<U> sendRequest(String url, T contract, Class<V> responseType, Function<V, U> transform)
{
WebClient webClient = WebClient.create("http://localhost:8080/");
WebClient.ResponseSpec foo = webClient.post()
.uri(url)
.body(Mono.just(contract), contract.getClass())
.retrieve();
Mono<V> mono = foo.bodyToMono(responseType);
Mono<U> trans = mono.map(transform);
return trans;
}
@GetMapping("/startClassCastException")
public Mono<String> startClassCastException()
{
return this.<String, String, ViewModel> sendRequestClassCastException("fetchViewModel", "contract", v -> (String) v.getResult().get("outputString"));
}
private <T, U, V> Mono<U> sendRequestClassCastException(String url, T contract, Function<V, U> transform)
{
ParameterizedTypeReference<T> contractType = new ParameterizedTypeReference<T>() {};
ParameterizedTypeReference<V> responseType = new ParameterizedTypeReference<V>() {};
WebClient webClient = WebClient.create("http://localhost:8080/");
WebClient.ResponseSpec foo = webClient.post()
.uri(url)
.body(Mono.just(contract), contractType)
.retrieve();
Mono<V> mono = foo.bodyToMono(responseType);
Mono<U> trans = mono.map(transform); // ClassCastException in Lambda
return trans;
}
}
关于spring-boot - SpringBoot - WebFlux 获取 ClassCastException 的通用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67851149/
我正在编写一个 mapreduce 应用程序,它接受(键,值)格式的输入并只显示与 reducer 输出相同的数据。 这是示例输入: 1500s 1 1960s 1 Aldus 1 在下面
我不明白,我有一个典型的消息源 content.Language 我可以得到它就像 @Autowire protec
我已经为抽屉导航编写了一个运行良好的程序,但最近我尝试为个人资料图片和 TextView 放置一个 ImageView,之后它给了我一个 ClassCastException。 main_activi
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
@Override public void onPause() { super.onPause(); save(notes.itemSelected); } @Override pub
描述 我正在尝试创建一种自定义语言,我想将词法分析器规则与解析器规则分开。此外,我的目标是将词法分析器和解析器规则进一步划分为特定文件(例如,通用词法分析器规则和关键字规则)。 但我似乎无法让它发挥作
我正在尝试使用以下代码为给定的 Runnable 对象创建代理: public class WorkInvocationHandler implements InvocationHandler {
我有两个非常简单的类,一个扩展了另一个: public class LocationType implements Parcelable { protected int locid =
我遇到了 ClassCastException :Cannot cast my.package.classA to my.package.classA.请注意,(规范)类(名称)是相同的。 我知道这应
我有一个代码试图将一个函数包装在另一个执行动态类型检查的函数中: class Base class Foo extends Base class Bar extends Base object Mai
我使用hadoop 0.18.3遇到以下错误 java.lang.ClassCastException:org.apache.hadoop.io.Text无法转换为org.apache.hadoop.
在 org.dozer.BeanFactory.createBean(Object, Class, String) 的实现中我尝试将对象转换为它的类型。如果我部署所有 bundle ,即关闭并启动所有
我有这个代码: package Maven_test.Maven_project_test; public class Test { class A { int i = 10;
我一直在尝试对 Wicket 的 WebSession 进行子类化,以便可以实现基本的身份验证系统。我已遵循 Wicket 引用库中的指南。当我在网页中尝试以下操作时,出现 ClassCastExce
我正在构建一个 kotlin AAR 库,我需要在发布之前对其进行混淆。我有以下结构: package com.example.token interface TokenManager { s
Kotlin 引入了 here 中描述的声明站点差异. 在某些情况下,泛型参数的 out/in 关键字可能会导致 ClassCastException。我的程序如下所示。 fun main(args:
我正在 AnyLogic 中进行基于代理的传染病流行模拟。我的模型中有两种代理类型 - 人员和建筑物。我正在尝试编写一个函数来计算代理类型“人员”在任何给定时间点所具有的传染性接触数量。下面是我的函数
我有一个 EditContact 类。打开后,它会显示哪些复选框已选中或未选中。这是通过我的适配器中的一些代码完成的,它可以正常工作: //This is for EditContact, t
这个问题已经有答案了: 奥 git _a (2 个回答) 已关闭 5 年前。 我正在获取 ClassCastException 。这两个类来自不同的 jar,但是JettyContinuationPr
我想在 Java 中使用一组对,但是当我调用 contains() 来查看它是否已包含特定对时,我总是会得到 ClassCastException >。有没有办法避免这种行为? 它的实例化如下: pr
我是一名优秀的程序员,十分优秀!