微服务中使用Map<String,Object>类型强转失败问题java.util.LinkedHashMap cannot be cast to com.xxx.xxx

场景:

使用微服务后,商品类别服务要调用商品服务,并实现分页处理,在商品类别服务接口中解析得到并强制类型转换Map中的商品记录信息

商品类别接口如下:
// 定义一个接口接收分页类型参数,返回map(total,List<Product>)
@GetMapping("/productsByPage")  // ProductDTO(List<Product>,Integer total)
public Map<String, Object> findByCategoryIdAndPage(Integer page, Integer rows, Integer categaoryId) {
  log.info("当前页:{} 每页显示记录数:{} 当前类别id:{}", page, rows, categaoryId);
  // 根据类别id分页查询符合当前页集合数据  List<Product>
  // 根据类别id查询当前类别下总条数   total
  HashMap<String, Object> map = new HashMap<>();

  List<Product> products = new ArrayList<>();
  products.add(new Product(1, "iphone13", 8888.88, new Date()));
  products.add(new Product(2, "iphone14", 9999.88, new Date()));
  products.add(new Product(3, "iphone15", 10000.88, new Date()));

  int tatal = 100;
  map.put("rows", products);
  map.put("total", tatal);
  return map;
}
Feign接口如下:
@FeignClient(value = "PRODUCT")  // value: 用来书写调用服务的服务id
public interface ProductClient {


  // 声明调用商品服务根据当前页,显示行数,类别id去查询所需要记录
  // ProductDTO(List<Product>,Integer total)
  @GetMapping("/productsByPage")
  Map<String, Object> findByCategoryIdAndPage(
      @RequestParam("page") Integer page,
      @RequestParam("rows") Integer rows,
      @RequestParam("categaoryId") Integer categaoryId);
}
调用商品服务接口:
@GetMapping("/categoryByPage")
public Map<String,Object> categoryByPage(){
  log.info("cateforyByPage");
  Map<String, Object> objectMap = productClient.findByCategoryIdAndPage(1, 5, 1);
  return objectMap;
}
前端返回信息:

依照这个流程下来表面看是没什么问题的,但是如果说我想要在调用商品服务接口中将返回的Map中的rows进行操作,如下:

@GetMapping("/categoryByPage")
public Map<String,Object> categoryByPage(){
  log.info("cateforyByPage");
  Map<String, Object> objectMap = productClient.findByCategoryIdAndPage(1, 5, 1);

  List<Product> rows = (List<Product>)(objectMap.get("rows"));
  rows.forEach(product -> log.info("product:"+product));

  return objectMap;
}

可以看到LinkedHashMap底层是没有办法帮进行强制类型转换的,因为rows底层是一个json格式数组的字符串,底层转为对象的时候不知道是哪个类型,前端能够转换为json格式数组是因为它把rows当做object去转

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CNBZadxn-1639115699208)(SpringCloud 微服务工具集v1.1.assets/image-20211210104109985.png)]

定义方法返回值类型为Map<String,Object>,因为value是object,就会导致map转换为json的时候它原始的product类型丢失了,所以到后面object才无法强转为product类型,原来的product类型在上一个被调用的服务中。

解决方法:

在@RestController类中,虽然我们定义的接口返回值是Map<String,Object>但是它响应给我们的是map转换为json,json就是普通的字符串,我们就把它当成一个字符串去处理,被调用的服务不变,将Feign接口和发请求的接口返回值从Map<String,Object>修改为String

// 声明调用商品服务根据当前页,显示行数,类别id去查询所需要记录
// ProductDTO(List<Product>,Integer total)
@GetMapping("/productsByPage")
String findByCategoryIdAndPage(
    @RequestParam("page") Integer page, 
    @RequestParam("rows") Integer rows,
    @RequestParam("categaoryId") Integer categaoryId);
}

通过使用fastjson将获取出来的字符串转换为对象,json的反序列化
fastjson依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
 </dependency>

通过jsonObject解析String为JSONObject,进入JSONobject我们发现,其实现了Map接口,JSONObject本身就是一个Map

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gCVFlOvO-1639115699209)(SpringCloud 微服务工具集v1.1.assets/image-20211210134703749.png)]

请求服务接口:
@GetMapping("/categoryByPage")
  public String categoryByPage(){
    log.info("cateforyByPage");
    String result = productClient.findByCategoryIdAndPage(1, 5, 1);
    // 自定义json反序列化  对象转为json(序列化)  json转为对象(反序列化)
    // 第一次反序列化,从String转换为JSONObject(Map)
    JSONObject jsonObject = JSONObject.parseObject(result);

    Object row = jsonObject.get("rows");
    // 第二次反序列化
    jsonObject.parseArray(row.toString(),Product.class).forEach(product -> log.info("product:{}",product));

    return result;
  }

至此转换成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pYJNXSyf-1639115699209)(SpringCloud 微服务工具集v1.1.assets/image-20211210134937659.png)]

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值