zoukankan      html  css  js  c++  java
  • spring学习笔记---第三方SDK(Rest API)和Jaskson的巧用

    前言:
      其实我以前一直不懂电商, 以及电商中所涉及的业务概念. 对于SKU等名词, 觉得有些玄乎. 对其背后的数据模型, 也有莫名的未知恐惧感: 庞大而理不清头绪. 不过最近有机会接触了微商(有赞), 身体力行, 感觉加深了一些了解. 对之前一直谈到的店铺ISV, 也明白其的工作内容.
      有赞(口袋通)做得真心的赞, 不过其java版的sdk, 始终觉得有些粗糙. 比如其返回结果是裸json字符串, 对于javaer而言, 习惯了pojo, 直接处理之还是显得有些麻烦, 因此我们需要在此基础上, 再做点额外的工作.
      本篇文章, 将结合这个例子, 来讲解下jaskson的妙用.

    相关文章:
      一. Jackson的使用和定制.
      这篇文章, 主要是服务端中, jackson库是如何扮演重要的角色. 本文是着重讲述, 在服务调用方, jackson是如何起到相应的作用的.

    吐槽:
      有赞API在线文档说明, 官方网址: http://open.koudaitong.com/doc.
      JAVA版SDK的Sample样例分析:

    public class KDTApiTest {
      private static final String APP_ID = "app_id"; //这里换成你的app_id
      private static final String APP_SECRET = "app_secret"; //这里换成你的app_secret
    	
      /*
       * 测试获取单个商品信息
       */
      private static void sendGet(){
        String method = "kdt.item.get";
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("num_iid", "2651514");
        KdtApiClient kdtApiClient;
        HttpResponse response;
        try {
          kdtApiClient = new KdtApiClient(APP_ID, APP_SECRET);
          response = kdtApiClient.get(method, params);
          System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
          BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
          StringBuffer result = new StringBuffer();
          String line = "";
          while ((line = bufferedReader.readLine()) != null) {
            result.append(line);
          }
          System.out.println(result.toString());
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }	

      从简单的sample代码中, 可以发现其ApiClient是对HttpClient做个一个简单的封装, 但封装并不彻底, 调用时和结果响应处理都有些麻烦.
      我大致猜测其结果为何就返回一个json字符串, 让解析的工作留给平台开发者. 不是懒, 而是因为返回结果的变动可能性比较大, 不敢轻易定制为对应的POJO类对象.
      返回的JSON字符串如下所示:

    {"response":{"item":{"cid":5000000,"promotion_cid":0,"tag_ids":"58279885","skus":[{"num_iid":105744782,"sku_id":35872379,"sku_unique_code":"10574478235872379", "quantity":"9999","outer_id":""}, ...

      注: 顶级元素为response, item对应具体的商品信息.
      无论如何, json的解析工作, 还是省不了的, 那如何处理呢?
      可以引入JSONObject, 按json字符串的层次结构来处理, 比如如下所示:

    JSONObject root = JSONObject.fromString(jsonText);
    JSONObject item = root.getJSONObject("response").getJSONObject("item");

      注: 这种编写方式, 非常的繁琐, 一点也不利于程序的快速处理, 那是否有利器来解决该问题呢? 我们的大英雄--jackson, 即将出马.

    解决方案:
      针对上述例子的kdt.item.get接口, 定义相应的POJO类.

    @JsonIgnoreProperties(ignoreUnknown = true)
    @JsonRootName("response")
    public class KdtItemGetResult {
    
      @JsonProperty("item")
      private GoodsDetailVO item;
    
      public GoodsDetailVO getItem() {
        return item;
      }
    
      public void setItem(GoodsDetailVO item) {
        this.item = item;
      }
    }

      注: POJO类, @JsonRootName可以设定Root元素, 用于剥离最外层, @JsonProperty用于设定对应json的key和属性的映射关系, @JsonIgnoreProperties(ignoreUnknown=true), 用于挑选需要的元素, 避开因为没有对应的pojo类属性而报错.

    @JsonIgnoreProperties(ignoreUnknown = true)
    public class GoodsDetailVO {
      @JsonProperty("num_iid")
      private long numIid;
      @JsonProperty("alias")
      private String alias;
      @JsonProperty("title")
      private String title;
    } 

      注: 其自然支持类层次结构的映射转换.
      那么, 我们在继续修改下调用接口, 如下所示: 

    public KdtItemGetResult kdtItemGet(long numIid) {
    
      String method = "kdt.item.get";
      HashMap<String, String> params = new HashMap<String, String>();
      params.put("num_iid", "" + numIid);
    
      KdtApiClient kdtApiClient;
      HttpResponse response;
    
      try {
        kdtApiClient = new KdtApiClient(APP_ID, APP_SECRET);
        response = kdtApiClient.get(method, params);
        // System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        StringBuffer result = new StringBuffer();
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {
          result.append(line);
        }
        System.out.println(result.toString());
    
        String jsonText = result.toString();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
        KdtItemGetResult kigr = objectMapper.readValue(jsonText, KdtItemGetResult.class);
    
        return kigr;
      } catch (Exception e) {
        // e.printStackTrace();
      }
      return null;
    }

      注: 除了请求的处理, 依旧如前, 但对json转换为pojo的处理, 变得非常的简洁.
      其核心的代码就如下几句:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true); // 支持@JsonRootName的特性
    KdtItemGetResult kigr = objectMapper.readValue(jsonText, KdtItemGetResult.class);
    return kigr;

      当然rest api的调用, 有可能失败, 再在外层添加下TResult<T>的封装即可.

    public class TResult<T> {
      private boolean success = false;
      private int errCode = 0;
      private String errMsg = "OK";
      private T value = null;
    }

      如你所看到的, 封装处理就非常的方便, 借用一句广告词: 妈妈, 再也不用担心粗糙的第三方SDK了.

    总结:
      尽量让优秀的框架, 替你做繁琐的重复工作. 这是一个非常重要的提高工作效率的方式. 临近结笔, 发现写得虎头蛇尾, 权做笔记.

    公众号&游戏站点:
      个人微信公众号: 木目的H5游戏世界
      

  • 相关阅读:
    Jboss部署war以及获取Resource的真实路径
    命令行获取docker远程仓库镜像列表
    Hibernate5 与 Spring Boot2 最佳性能实践
    Spring Bean的一生
    Spring中统一相同版本的api请求路径的一些思考
    Java并发工具类CountDownLatch源码中的例子
    (转载)23种设计模式的uml图表示及通俗介绍
    GeoHash核心原理解析
    如何保证服务器的安全?
    小强升职记
  • 原文地址:https://www.cnblogs.com/mumuxinfei/p/4874235.html
Copyright © 2011-2022 走看看