Spring RESTTemplate中的泛型

92

我有一个类似于这样的类:

public class Wrapper<T> {

 private String message;
 private T data;

 public String getMessage() {
    return message;
 }

 public void setMessage(String message) {
    this.message = message;
 }

 public T getData() {
    return data;
 }

 public void setData(T data) {
    this.data = data;
 }

}

我使用RestTemplate如下:

...
Wrapper<Model> response = restTemplate.getForObject(URL, Wrapper.class, myMap);
Model model = response.getData();
...

然而,它会抛出一个:
ClassCastException

我看到了这个问题:尝试在Java中使用Jackson时出现问题,但没有帮助。有一些与我的问题相关的主题,例如:https://jira.springsource.org/browse/SPR-7002https://jira.springsource.org/browse/SPR-7023

有什么想法吗?

PS:我的错误是:

java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to a.b.c.d.Model

我认为RestTemplate无法理解我的泛型变量,可能会将其视为Object而不是泛型T。因此它变成了一个LinkedHashMap。您可以从这里阅读到相关信息。它说在解释它所编组的内容时:

JSON类型 | Java类型

object | LinkedHashMap


请同时放置异常跟踪。 - Santosh
我认为这个问题的解决方案已经在3.2版本中添加了SPR-7023 - raksja
你有没有找到解决方案?我正在使用ParameterizedTypeReference,当我传递Map<String, String>时它可以工作,但是当我传递代表您模型中的“data”的具体类时它无法工作。 - danieljimenez
你找到解决方案了吗? - Prasanna Kumar H A
3个回答

172

为了解决这个问题,ParameterizedTypeReference在3.2 M2中被引入。

Wrapper<Model> response = restClient.exchange(loginUrl, 
                          HttpMethod.GET, 
                          null, 
                          new ParameterizedTypeReference<Wrapper<Model>>() {}).getBody();

然而,postForObject/getForObject变体并未被介绍。


1
我为你们尝试了另一种选择,@alexanoid。首先将响应作为“String”获取,然后使用Jackson将字符串解析为泛型对象,如下所示:String body = restTemplate.exchange(request,String.class).getBody(); ObjectMapper mapper=new ObjectMapper(); DataTablesOutput readValue = mapper.readValue(body, DataTablesOutput.class); - Alter Hu
2
为什么模型不能是泛型的?例如:Model<InnerModel> - zygimantus
1
为了补充Alter的回答,您可以使用: mapper.readValue(body, new TypeReference<Wrapper<Model>>(){}); - cs94njw
1
我的问题也是为什么我们不能在这里将模型也变成通用的? - u91

12

我认为您唯一能做的就是创建一个继承Wrapper类并使用model作为泛型的新类。

class WrapperWithModel extends Wrapper<Model>{};

WrapperWithModel response = restTemplate.getForObject(URL, WrapperWithModel.class);

这并不是最佳解决方案,但至少你不需要手动拆解响应。


我个人不太喜欢这个解决方案,但现在我无法升级Spring以使用其新的参数化类型对象(https://jira.springsource.org/browse/SPR-7023),所以这已经足够好了。谢谢。 - Gustavo Matias
它必须是静态类。 - Adam Silenko

2
不要在RestTemplate中使用泛型。使用包装对象来封装请求和响应对象,并隐藏泛型信息。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接