【问题标题】:Spring RestTemplate deserialising generic list with wrapperSpring RestTemplate 使用包装器反序列化通用列表
【发布时间】:2020-08-24 18:40:06
【问题描述】:

目前我有以下通用包装器,用于响应我正在使用的其余服务 -

class Response<T> {
  private T data;
  private boolean success;
  ...
}

我想使用通用的 Util 方法来使用我从该服务接收到的所有类型的 T data 对象。下面是我目前写的Util方法sn -p -

public <T> List<T> invokeServiceForList(ServiceRequestFactory factory) throws ServiceException {
        ResponseEntity<Response<List<T>>> responseEntity = null;
        List<T> data = null;
        try {
            responseEntity = restTemplate.exchange(factory.getUriBuilder().toUriString(), factory.getHttpMethod(), factory.getRequestEntity(), new ParameterizedTypeReference<Response<List<T>>>() {});

            if (responseEntity.getBody() != null && !responseEntity.getBody().isSuccess()) {
                LOG.error("Response received from service with errors");
                throw new Exception("Error");
            }

            data = responseEntity.getBody().getData();

        } catch (Exception e) {
            LOG.error("Internal service exception while connecting to service", e);
            throw new Exception("Internal Error");
        }

        return data;
    }

我目前正在通过以下方式调用上述方法-

ServiceDelegate delegate = new ServiceDelegate(restTemplate);
List<User> users = delegate.invokeServiceForList(factory);

当我的 T 是一个简单的 POJO(例如 User)时,我将得到一个 ArrayList&lt;LinkedHashMap&lt;String, Object&gt;&gt; 作为此方法的输出,而不是 ArrayList&lt;User&gt;

理想情况下,我希望委托方法推断类型 User,并且我不想将 ParameterizedTypeReference 作为参数显式传递给此方法。有人能告诉我我在这里做错了什么或者还有什么可以做的吗?

【问题讨论】:

  • 在方法中的参数中取ParameterizedTypeReference值,使其像ParameterizedTypeReference&lt;List&lt;T&gt;&gt; type一样工作,并在调用方法时发送确切的类型引用
  • 请告诉我们你是怎么打电话给invokeServiceForList(ServiceRequestFactory)的? TIA。
  • @deduper ServiceDelegate delegate = new ServiceDelegate(restTemplate); List&lt;User&gt; users = delegate.invokeServiceForList(factory); 这里ServiceDelegate 包含invokeServiceForList 方法
  • 谢谢先生。您是否需要更改 ServiceDelegate.invokeServiceForList(ServiceRequestFactory) 的签名?
  • @deduper 我可以,如果需要的话。但我不希望按照 Rono 的建议添加 ParameterizedTypeReference 作为参数。任何其他可以直接推断对象类型的替代方法对我来说真的很有帮助。提前致谢

标签: java spring-boot generics resttemplate


【解决方案1】:

您可以尝试从以下位置删除菱形中的泛型:

 new ParameterizedTypeReference<Response<List<T>>>() {}

到:

new ParameterizedTypeReference<>() {}

之后,我会在调试模式下检查变量 responseEntity 并查看里面的内容。 现在您将能够从 responseEntity 中正确提取所需的数据。

【讨论】:

  • 谢谢先生。 The docs for ParameterizedTypeReference&lt;T&gt; say: „为了捕获泛型类型并在运行时保留它,您需要创建一个子类(最好是匿名内联类),如下所示:ParameterizedTypeReference&lt;List&lt;String&gt;&gt; typeRef = new ParameterizedTypeReference&lt;List&lt;String&gt;&gt;() {};)“。给你两个问题。请问:(Q1) 在您的示例中,填写 T 的类型参数是什么? (Q2)为什么 OP 不应该按照文档的建议去做?
【解决方案2】:

一种解决方法是,在方法中的参数中取ParameterizedTypeReference 值,如ParameterizedTypeReference&lt;Response&lt;List&lt;T&gt;&gt;&gt; 类型,并在调用方法时发送确切的类型引用

在方法中添加参数

public <T> List<T> invokeServiceForList(ServiceRequestFactory factory,
            ParameterizedTypeReference<Response<List<T>>> type) throws ServiceException {
    ...
    restTemplate.exchange(factory.getUriBuilder().toUriString(), factory.getHttpMethod(), factory.getRequestEntity(), type);
    ...
}

然后这样调用

List<User> users = delegate.invokeServiceForList(factory, new ParameterizedTypeReference<Response<List<User>>>() {});

【讨论】:

  • 谢谢罗诺。 — „在方法中添加参数public &lt;T&gt; List&lt;T&gt; invokeServiceForList(ServiceRequestFactory factory, ParameterizedTypeReference&lt;Response&lt;List&lt;T&gt;&gt;&gt; type)“ — 你能帮我理解为什么@VinayNikhil 需要更改他的方法签名吗? TIA。
  • @deduper 因为在初始化ServiceDelegate时没有指定泛型参数,所以无法知道方法内部的T是什么。由于我不了解整个课程,因此我提供了一种以最少信息进行修复的方法。
  • ...因为在初始化ServiceDelegate的时候没有指定泛型参数,所以无法知道方法里面的T是什么...“——谢谢你罗诺。 @VinayNikhil 在评论中写道,他的 ServiceDelegate.invokeServiceForList(ServiceRequestFactory) 方法将被称为:List&lt;User&gt; users = delegate.invokeServiceForList(factory);。那么为什么不能从方法调用分配中推断出 TList&lt;User&gt; users 呢? TIA。
  • @deduper 你怎么知道OP使用的是哪个java版本?
  • ...你怎么知道 OP 使用了哪个 Java 版本?...“—我不知道 @VinayNikhil 使用了哪个 Java 版本。你能帮我理解为什么版本对他的问题、你的回答和方法调用返回类型推断很重要吗? TIA。
猜你喜欢
  • 2015-02-26
  • 2020-09-10
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2020-04-03
  • 2014-03-11
  • 1970-01-01
  • 2016-10-23
相关资源
最近更新 更多