在公司的数据中心项目里使用了Feign,进行接口的调用,在返回一个复杂的对象时候,出现下面的一个错误:
1 java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to xxx
大致意思就是 LinkedHashMap 不能够转换成 xxx 对象,我很奇怪!因为这个接口相关的地方都没有使用到 LinkedHashMap,他是从哪里冒出来的?我开始调试下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @Override public List<EsFilterKV> getFilterKV (Integer companyId, Integer appId, Long usrId, String filterName) { if (StringUtils.isEmpty(filterName)){ return null ; } List<CompanyDistributionFilterGroup> distributionFilterGroupList = companyDistributionService.findDistributionFilterGroupList(companyId,true ); List<ProductDocument> productDocumentList = new ArrayList<ProductDocument>(100 ); try { for (CompanyDistributionFilterGroup group: distributionFilterGroupList) { List<FilterItem> filterItemList = filterGroupFilterService.findFilterItemList(group.getFilterGroupId()); MtSearchFilterRequest request = new MtSearchFilterRequest(); request.setFilterItemList(filterItemList); MtSearchResult mtSearchResult = productSearchService.search(request); productDocumentList.addAll(mtSearchResult.getData()); } } catch (MtException e) { e.printStackTrace(); } List<Long> longList = productDocumentList.stream().map(p->p.getId()).distinct().collect(Collectors.toList()); if (CollectionUtils.isEmpty(longList)){ return null ; } List<Map> idValueList = productPackageService.findPackageIdValueList(longList,filterName,true ); if (CollectionUtils.isEmpty(idValueList)){ return null ; } List<EsFilterKV> esFilterKVs = new ArrayList<EsFilterKV>(idValueList.size()); for (Map map: idValueList){ EsFilterKV esFilterKV = new EsFilterKV(); esFilterKV.setName(map.get("name" ).toString()); esFilterKV.setId(new Long(map.get("id" ).toString())); esFilterKV.setJsonName("{'id':" +esFilterKV.getId()+",'name':'" +esFilterKV.getName()+"'}" ); esFilterKVs.add(esFilterKV); } return esFilterKVs; }
我发现在 productDocumentList.addAll(mtSearchResult.getData()); 这一行,productDocumentList里面放的全是LinkedHashMap,不是想象中的对象列表。通过面向百度编程,我把productSearchService.search()这个方法返回的泛型给去掉了,指定了真实的类型,从而解决了上面的问题!
通过百度得知有不少人遇到这种问题,有个感觉比较靠谱的解释如下:
因为rpc远程调用在底层还是使用的HTTPClient,所以在传递参数的时候,必定要有个顺序,当你传递map的时候map里面的值也要有顺序,不然服务层在接的时候就出问题了,所以它才会从map转为linkedhashMap!spring 有一个类叫ModelMap,继承了linkedhashMap public class ModelMap extends LinkedHashMap ,所以一个接口返回的结果就可以直接用ModelMap来接,注意ModelMap是没有泛型的,不管你返回的结果是什么类型的map,泛型是多复杂的map,都可以直接new一个Modelmap,用它来接返回的结果!!!