在具有泛型参数的泛型方法中使用 Spring RestTemplate [英] Using Spring RestTemplate in generic method with generic parameter

查看:42
本文介绍了在具有泛型参数的泛型方法中使用 Spring RestTemplate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在 Spring RestTemplate 中使用泛型类型,我们需要使用 ParameterizedTypeReference (无法获得通用响应实体,其中 T 是通用类SomeClass)

To use generic types with Spring RestTemplate we need to use ParameterizedTypeReference (Unable to get a generic ResponseEntity<T> where T is a generic class "SomeClass<SomeGenericType>")

假设我有一些课程

public class MyClass {
    int users[];

    public int[] getUsers() { return users; }
    public void setUsers(int[] users) {this.users = users;}
}

还有一些包装类

public class ResponseWrapper <T> {
    T response;

    public T getResponse () { return response; }
    public void setResponse(T response) {this.response = response;}
}

所以如果我尝试做这样的事情,一切都很好.

So if I'm trying to do something like this, all is OK.

public ResponseWrapper<MyClass> makeRequest(URI uri) {
    ResponseEntity<ResponseWrapper<MyClass>> response = template.exchange(
        uri,
        HttpMethod.POST,
        null,
        new ParameterizedTypeReference<ResponseWrapper<MyClass>>() {});
    return response;
}

但是当我尝试创建上述方法的通用变体时......

But when I'm trying to create generic variant of the above method ...

public <T> ResponseWrapper<T> makeRequest(URI uri, Class<T> clazz) {
   ResponseEntity<ResponseWrapper<T>> response = template.exchange(
        uri,
        HttpMethod.POST,
        null,
        new ParameterizedTypeReference<ResponseWrapper<T>>() {});
    return response;
}

...并像这样调用这个方法...

... and calling this method like so ...

makeRequest(uri, MyClass.class)

... 而不是获取 ResponseEntity> 对象,我得到的是 ResponseEntity> 对象.

... instead of getting ResponseEntity<ResponseWrapper<MyClass>> object I'm getting ResponseEntity<ResponseWrapper<LinkedHashSet>> object.

我该如何解决这个问题?是 RestTemplate 的错误吗?

How can I solve this problem? Is it a RestTemplate bug?

更新 1感谢@Sotirios,我理解了这个概念.不幸的是,我是在这里新注册的,所以我不能评论他的回答,所以写在这里.我不确定我是否清楚地理解如何使用 MapClass 键(由@Sotirios 在他的回答末尾提出)来实施建议的方法来解决我的问题.有人介意举个例子吗?

UPDATE 1 Thanks to @Sotirios I understand the concept. Unfortunately I'm newly registered here so I cant comment on his answer, so writing it here. Im not sure that I clearly understand how to implement the proposed approach to solve my problem with Map with Class key (Proposed by @Sotirios in the end of his answer). Would someone mind to give an example?

推荐答案

不,这不是错误.这是 ParameterizedTypeReference hack 工作方式的结果.

No, it is not a bug. It is a result of how the ParameterizedTypeReference hack works.

如果你看看它的实现,它使用 Class#getGenericSuperclass() 说明

If you look at its implementation, it uses Class#getGenericSuperclass() which states

返回代表实体直接超类的类型(类、接口、原始类型或void)由此类表示.

Returns the Type representing the direct superclass of the entity (class, interface, primitive type or void) represented by this Class.

如果超类是参数化类型,返回的Type对象必须准确反映源中使用的实际类型参数代码.

If the superclass is a parameterized type, the Type object returned must accurately reflect the actual type parameters used in the source code.

所以,如果你使用

new ParameterizedTypeReference<ResponseWrapper<MyClass>>() {}

它会准确地为 ResponseWrapper 返回一个 Type.

it will accurately return a Type for ResponseWrapper<MyClass>.

如果你使用

new ParameterizedTypeReference<ResponseWrapper<T>>() {}

它会准确地为 ResponseWrapper 返回一个 Type,因为这就是它在源代码中的显示方式.

it will accurately return a Type for ResponseWrapper<T> because that is how it appears in the source code.

当 Spring 看到 T,它实际上是一个 TypeVariable 对象时,它不知道要使用的类型,所以它使用它的默认值.

When Spring sees T, which is actually a TypeVariable object, it doesn't know the type to use, so it uses its default.

您不能按照您提议的方式使用 ParameterizedTypeReference,使其在接受任何类型的意义上成为通用的.考虑编写一个 Map,其中键 Class 映射到该类的预定义 ParameterizedTypeReference.

You cannot use ParameterizedTypeReference the way you are proposing, making it generic in the sense of accepting any type. Consider writing a Map with key Class mapped to a predefined ParameterizedTypeReference for that class.

您可以子类化 ParameterizedTypeReference 并覆盖其 getType 方法以返回适当创建的 ParameterizedType根据 IonSpin 的建议.

You can subclass ParameterizedTypeReference and override its getType method to return an appropriately created ParameterizedType, as suggested by IonSpin.

这篇关于在具有泛型参数的泛型方法中使用 Spring RestTemplate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆