Java Spring RestTemplate 和泛型类型 ParameterizedTypeReference 集合,如 List<T>
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36915823/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring RestTemplate and generic types ParameterizedTypeReference collections like List<T>
提问by vels4j
An Abstract controller class requires List of objects from REST. While using Spring RestTemplate its not mapping it to required class instead it returns Linked HashMAp
抽象控制器类需要来自 REST 的对象列表。使用 Spring RestTemplate 时,它没有将其映射到所需的类,而是返回 Linked HashMAp
public List<T> restFindAll() {
RestTemplate restTemplate = RestClient.build().restTemplate();
ParameterizedTypeReference<List<T>> parameterizedTypeReference = new ParameterizedTypeReference<List<T>>(){};
String uri= BASE_URI +"/"+ getPath();
ResponseEntity<List<T>> exchange = restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);
List<T> entities = exchange.getBody();
// here entities are List<LinkedHashMap>
return entities;
}
If I use,
如果我使用,
ParameterizedTypeReference<List<AttributeInfo>> parameterizedTypeReference =
new ParameterizedTypeReference<List<AttributeInfo>>(){};
ResponseEntity<List<AttributeInfo>> exchange =
restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);
It works fine. But can not put in all subclasses, any other solution.
它工作正常。但不能放入所有子类,任何其他解决方案。
采纳答案by Rossiar
I worked around this using the following generic method:
我使用以下通用方法解决了这个问题:
public <T> List<T> exchangeAsList(String uri, ParameterizedTypeReference<List<T>> responseType) {
return restTemplate.exchange(uri, HttpMethod.GET, null, responseType).getBody();
}
Then I could call:
然后我可以打电话:
List<MyDto> dtoList = this.exchangeAsList("http://my/url", new ParameterizedTypeReference<List<MyDto>>() {});
This did burden my callers with having to specify the ParameterizedTypeReference
when calling, but meant that I did not have to keep a static mapping of types like in vels4j's answer
这确实给我的调用者带来了必须指定ParameterizedTypeReference
调用时间的负担,但这意味着我不必像 vels4j 的回答那样保留类型的静态映射
回答by vels4j
Couldnt find a solution from Spring, hence I have done it with ParameterizedTypeReference
in HashMap
like
不可能找到春天的解决方案,因此我与它做ParameterizedTypeReference
的HashMap
像
public final static HashMap<Class,ParameterizedTypeReference> paramTypeRefMap = new HashMap() ;
static {
paramTypeRefMap.put(AttributeDefinition.class, new ParameterizedTypeReference<List<AttributeDefinition>>(){} );
paramTypeRefMap.put(AttributeInfo.class, new ParameterizedTypeReference<List<AttributeInfo>>(){} );
}
and used it
并使用它
ParameterizedTypeReference parameterizedTypeReference = paramTypeRefMap.get(requiredClass);
ResponseEntity<List> exchange = restTemplate.exchange(uri, HttpMethod.POST, entity, parameterizedTypeReference);
回答by Moesio
Using ParameterizedTypeReference
for a List<Domain>
, when Domain is an explicit class, that ParameterizedTypeReference
works well, like this:
使用ParameterizedTypeReference
for a List<Domain>
,当 Domain 是一个显式类时,ParameterizedTypeReference
效果很好,如下所示:
@Override
public List<Person> listAll() throws Exception {
ResponseEntity<List<E>> response = restTemplate.exchange("http://example.com/person/", HttpMethod.GET, null,
new ParameterizedTypeReference<List<Person>>() {});
return response.getBody();
}
However, if a method listAll
is used in generic flavor, that list should be parameterized itself. The best way I found for this is:
但是,如果listAll
在通用风格中使用了一个方法,则该列表本身应该被参数化。我为此找到的最好方法是:
public abstract class WebServiceImpl<E> implements BaseService<E> {
private Class<E> entityClass;
@SuppressWarnings("unchecked")
public WebServiceImpl() {
this.entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
@Override
public List<E> listAll() throws Exception {
ResponseEntity<List<E>> response = restTemplate.exchange("http://example.com/person/", HttpMethod.GET, null,
new ParameterizedTypeReference<List<E>>() {
@Override
public Type getType() {
Type type = super.getType();
if (type instanceof ParameterizedType) {
Type[] responseWrapperActualTypes = { entityClass };
ParameterizedType responseWrapperType = new ParameterizedTypeImpl(List.class,
responseWrapperActualTypes, null);
return responseWrapperType;
}
return type;
}
});
return response.getBody();
}
}
回答by JRA_TLL
The easiest solution for me is to define an object MyOperationResult containing the list you expect as field and use restTemplate.getForObject to get this result.
对我来说,最简单的解决方案是定义一个对象 MyOperationResult ,其中包含您期望作为字段的列表,并使用 restTemplate.getForObject 来获取此结果。
回答by Ken Joyner
I did this a bit different. In my situation, I had a base class where I was implementing a set of CRUD operations and then using derived classes to implement specific resource types.
我这样做有点不同。在我的情况下,我有一个基类,我在其中实现了一组 CRUD 操作,然后使用派生类来实现特定的资源类型。
In the base class, I was trying to define a ParameterizedTypeReference as follows:
在基类中,我试图定义一个 ParameterizedTypeReference 如下:
ParameterizedTypeReference<ServicePagedResult<R>> typeRef =
new ParameterizedTypeReference<ServicePagedResult<R>>() {};
This didn't work so I ended up creating an abstract method in the base class:
这不起作用,所以我最终在基类中创建了一个抽象方法:
protected abstract ParameterizedTypeReference<ServicePagedResult<R>>
getServicePagedResultTypeRef();
and then in the derived classes:
然后在派生类中:
@Override
protected ParameterizedTypeReference<ServicePagedResult<AccountResource>>
getServicePagedResultTypeRef() {
return new ParameterizedTypeReference<ServicePagedResult<AccountResource>>() {};
}
I could then use that in the base class like:
然后我可以在基类中使用它,例如:
ResponseEntity<ServicePagedResult<R>> response = lbRestTemplate.exchange(
uri, HttpMethod.GET, null, getServicePagedResultTypeRef(), uriVariables);
回答by ELavicount
In case someone need a Kotlin solution, you can do:
如果有人需要 Kotlin 解决方案,您可以执行以下操作:
val responseType = object : ParameterizedTypeReference<Map<String, Any?>>() {}
val request = HttpEntity<Any?>(data)
val response = restTemplate.exchange(url, HttpMethod.POST, request, responseType)
val responseMap = response?.body as Map<String, Any>