zoukankan      html  css  js  c++  java
  • RestTemplate将响应数据转换为具有泛型的类对象

    前言:

    重要,RestTemplate在SpringBoot项目里即便通过HttpMessageConverters添加了Fastjson且优先级比jackson要高也不会在RestTemplate里生效

    ,换句话说RestTemplate如果要使用Fastjson还是要对RestTemplate进行额外配置,而不是在SpringBoot项目里配置了类型是HttpMessageConverters的Bean就可以了;

    方式可以参考:https://www.jianshu.com/p/c9644755dd5e

    一:没有泛型的情况(这里以POST举例,但是对于GET也是一样的)

    CommonResponse response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

    这里tokenRequest是请求体对象,将会由Fastjson序列化为JSON字符串,它所属的类无所谓是不是有泛型,因为可以通过member.getClass()获得(即tokenRequest中所有的成员的类型是确立的且可获取的);

    使用的时候最好用restTemplate.postForEntity()的而不要用restTemplate.postForObject(),后者不能设置Header,而且似乎也不能执行Multipart请求;

    二:有泛型的情况

    CommonResponse<TokenDataModel> response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

    这个时候就有问题了,因为CommonResponse在字节码里是泛型擦除的,它所有的泛型成员本质上就是一个Object类型的子类但是.class里没有记录到底是什么具体类,因此当获取的response的JSON字符串中:

    {
        "code": 8209,
        "code_description": "APPLICANT_SUCCESS",
        "data": {
            "cell_phone_number": "1111111111",
            "collect_website": "中国联通","token": "77785fb276ed47cb9a01ec52f9a133c8"
        },
        "message": "成功"
    }

    将data部分转换为泛型成员时RestTemplate将不知道该怎么转换,如果将T类型认为是Object,那么显然Object是没有cellPhoneNumber之类的属性的,所以RestTemplate的做法是将data部分的JSON字符串转换为了LinkedHashMap对象(key-value对);

    三:解决方式

    通过RestTemplate的exchange方法来解决:

    ParameterizedTypeReference<CommonResponse<TokenDataModel>> typeRef = new ParameterizedTypeReference<CommonResponse<TokenDataModel>>() {};
    // exchange并不对应于任何一种method,如GET、POST、PUT、DELETE,因此需要手动指定 CommonResponse
    <TokenDataModel> response = restTemplate.exchange(remoteUrl, HttpMethod.POST, new HttpEntity<>(tokenRequest), typeRef).getBody();

    四:单纯用Fastjson转换有泛型的类的方式

    CommonResponse<TokenDataModel> response = JSON.parseObject("{json string}", new com.alibaba.fastjson.TypeReference<CommonResponse<TokenDataModel>>(){});

    五:原理

    在java里,泛型类编译成.class后确实是泛型擦除,但是泛型类对象里是会(间接)存储泛型的实际类型的,因此需要new TypeReference<Test<RealType>>(){}产生一个对象;

    它内部是:

    // 获取匿名类对象的Generic父类,即Test<RealType>类型
    // 注意superClass并不是Class类对象,它应该理解为:
    // 为泛型类的子匿名类对象产生的一个与之一一对应的Type类对象(这个倒像真泛型)
    // 这个Type类对象里存储了此匿名类对象的所有泛型信息
    Type superClass = getClass().getGenericSuperclass();
  • 相关阅读:
    《Linux4.0设备驱动开发详解》笔记--第十四章:Linux网络设备驱动
    《Linux4.0设备驱动开发详解》笔记--第十三章:Linux块设备驱动
    《Linux4.0设备驱动开发详解》笔记--第十二章:Linux设备驱动的软件架构思想
    《Linux4.0设备驱动开发详解》笔记--第十一章:内存与I/O访问
    《Linux4.0设备驱动开发详解》笔记--第十章:Linux设备驱动中的中断与时钟
    《Linux4.0设备驱动开发详解》笔记--第九章:Linux设备驱动中的异步通知与同步I/O
    《Linux4.0设备驱动开发详解》笔记--第八章:linux设备驱动的阻塞与非阻塞
    《机器学习》(西瓜书)笔记(5-2)--神经网络
    《机器学习》(西瓜书)笔记(5-1)--神经网络
    《机器学习》(西瓜书)笔记(4)--决策树
  • 原文地址:https://www.cnblogs.com/silentdoer/p/9012599.html
Copyright © 2011-2022 走看看