博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
x-http-wrapper: 如何解决每次发版时,修改http相关代码造成的错误!(Android、iOS、h5)...
阅读量:6980 次
发布时间:2019-06-27

本文共 9414 字,大约阅读时间需要 31 分钟。

其实是我做了个开源工具(^__^),拿出来给大家鉴赏下,欢迎大家提意见

项目: 欢迎关注和star 。
功能:这是一个http相关代码的创建工具。

现在我们每一次发版,基本上都会涉及到http相关的修改,以此来满足发版的业务需求。

而在其中需要添加或修改的有http request、http request param、http response entity等其他相关的http代码。
而在多次的修改中,若前后端没有协调好,就有可能会造成之后的返工、重复修改与线上bug量的增加等问题。

现在的痛点

如何解决每次发版时,都需要新增、修改http相关代码!

如何解决每次发版时,修改http相关代码造成的错误!

解决思路: 规范

  1. 其实很简单,就是一个词“规范”,任何事情,只要我们有了一定的规范,就会有一定的流程、可追踪并且降低难度。

    我相信99.99%的公司,都会有相关的http接口文档提供给前端同学,而且也会自己的一套规范(不论是我现在依赖的apidocjs,还是上家公司的doc文件)。
    当然,肯定也有口头约定的情况,但这需要在之后,立即将约定转化为文档,提供给前端的同学。git、http都可以作为提供的形式。

  2. 我们依赖这个http的规范,就可以将http接口文档去解析转义为x-http-wrapper内部的API数据。

  3. 再来就是依赖一定的规范(x-http-wrapper的模板文件规范),将内部API数据转化为http相关文件。这样,每次只要接口文档更新过后,我们就可以根据文档生成各个程序内部可以运行的代码。
    这个功能与现在IDE中的getter、setter方法生成器功能其实是相同的原理!

x-http-wrapper介绍

  1. 这是一个http相关代码的创建工具。
  2. 现在能创建的http相关的文件类型有:http请求分类,http请求,请求方法参数,响应实体,响应实体中状态码列表和基础响应实体类。

    • HttpApi(http请求分类): 所有API请求的统一调用入口,统合所有的请求类别的接口,防止API接口分散。

      public class HttpApi { private static Account account; private static Data data; private static Message message; public static Account account() {     if (null == account) {         account = Account.getInstance();     }     return account; } public static Data data() {     if (null == data) {         data = Data.getInstance();     }     return data; } public static Message message() {     if (null == message) {         message = Message.getInstance();     }     return message; }}复制代码
    • Request(http请求): 单个请求分组中,所有的请求方法。

      public class Account extends BaseApi {  public static Account getInstance() {      return Helper.instance;  }  private static class Helper {      public static final Account instance = new Account();  }  private Account() {      super();  }  /**   * @version 2.0.0   * @requestUrl    * @title 初始化账号信息   *   */  public RequestHandle init(Context cxt001,      ResponseHandlerInterface response) {      // hide implementation  }  /**   * @version 2.0.0   * @title 扫二维码到 web 端进行操作   *   * @param context String desc   * @param project_id isOptional Integer desc   * @param scene isOptional String desc   * @param uuid_rand String desc   */  public RequestHandle qrcodeConfirm(Context cxt001,      String context, Integer project_id, String scene, String uuid_rand,       ResponseHandlerInterface response) {      // hide implementation  }  /**   * 缩略请求方法   */  public RequestHandle qrcodeConfirm(Context cxt001,      QrcodeConfirmRP.Parameter parameter,       ResponseHandlerInterface response) {      return qrcodeConfirm(cxt001,      parameter.context, parameter.project_id, parameter.scene, parameter.uuid_rand,       response);  }}复制代码
    • RequestParam(请求方法参数): 请求参数分组归类,对应单个请求,用于请求参数较多的情况,生成请求参数的分类实体类(请求参数也肯能有多个分类),减少请求方法的输入参数。

      /*** 请求方法参数*/public class QrcodeConfirmRP implements Serializable { public static final class Parameter implements Serializable {     /**      * type: String
      * isOptional : false
      * desc:

      扫码场景,枚举值

      */ public String context; /** * type: Integer
      * isOptional : true
      * desc:

      业务参数: 根据 context 的不同而不同

      */ public Integer project_id; /** * type: String
      * isOptional : true
      * desc:

      身份信息: 服务端会优先使用客户端传入的身份信息,当为”投资人“的时候必传

      */ public String scene; /** * type: String
      * isOptional : false
      * desc:

      从二维码扫描得到的唯一码

      */ public String uuid_rand; }}复制代码
    • Response(响应实体): 请求的相应数据model

      public class Init {  private long member_id;  private long member_role;  private long member_status;  private String ry_token;  private long step;  public long getMemberId() {
      return member_id;} public long getMemberRole() {
      return member_role;} public long getMemberStatus() {
      return member_status;} public String getRyToken() {
      return ry_token;} public long getStep() {
      return step;} public void setMemberId(long member_id) {
      this.member_id = member_id;} public void setMemberRole(long member_role) {
      this.member_role = member_role;} public void setMemberStatus(long member_status) {
      this.member_status = member_status;} public void setRyToken(String ry_token) {
      this.ry_token = ry_token;} public void setStep(long step) {
      this.step = step;}}复制代码
    • StatusCode(响应实体中状态码列表): 响应中所有状态码的枚举类

      public class StatusCode {  /** '') */  public static final int OK = 0;  /** '登录状态已过期,请重新登入') */  public static final int UNAUTHORIZED = 101;  /** '您没有权限查看') */  public static final int FORBIDDEN = 102;  /** '资源未找到') */  public static final int NOT_FOUND = 103;  /** '客户端请求错误') # 4XX客户端错误 */  public static final int CLIENT_ERROR = 228;  /** '服务器错误') # 5XX 服务器错误 */  public static final int SERVER_ERROR = 229;  /** '参数错误') */  public static final int PARAM_ERROR = 230;  /** '登录失败,请检查您的邮箱地址是否正确') */  public static final int LOGIN_FAIL_EMAIL_NOT_EXIST = 332;  /** '登录失败,请确认您的手机号是否正确') */  public static final int LOGIN_FAIL_MOBILE_NOT_EXIST = 333;  /** '登录失败,请检查密码是否正确') */  public static final int LOGIN_FAIL_PASSWORD_ERROR = 334;}复制代码
    • BaseResponse(基础响应实体类): 基础的响应实体类

      public class ResponseEntity
      { private int status_code; private String message; private Error error; private T data; public int getStatusCode() {
      return status_code;} public void setStatusCode(int status_code) {
      this.status_code = status_code;} public String getMessage() {
      return message;} public void setMessage(String message) {
      this.message = message;} public Error getError() {
      return error;} public void setError(Error error) {
      this.error = error;} public T getData() {
      return data;} public void setData(T data) {
      this.data = data;} public static class Error { private String detail; private List
      device_token; private List
      content; private List
      followed_id; public String getDetail() {
      return detail;} public void setDetail(String detail) {
      this.detail = detail;} public List
      getDeviceToken() {
      return device_token;} public void setDeviceToken(List
      device_token) { this.device_token = device_token;} public List
      getContent() { return content;} public void setContent(List
      content) { this.content = content;} public List
      getFollowedId() { return followed_id;} public void setFollowedId(List
      followed_id) { this.followed_id = followed_id;} }}复制代码
  3. http的数据来源,现阶段只有apidocjs这一个
    • 若有其他数据来源,可以配置api_data.source属性,然后添加对应的解析器,解析为xhw的model。

工具环境与依赖

  • 命令行运行jar文件: 需要java8及以上的版本
  • 开发环境:
    • Java的版本: java8及以上的版本
    • 开发平台: intellij idea
    • 依赖的jar: gson:2.8.0, rxjava:1.2.2, junit:4.12

快速使用入门

  1. 下载项目的Zip包,解压缩,从xhwt文件夹下,选取其中的一个包装器模板文件夹,作为目标包装器的配置,该文件夹在下面都叫做target dir
    • 例如:xhwt/asynchttp/non_version(这是android-async-http库的一个模板与配置);
  2. 获取接口数据文件(api_data.json:存储apidocjs生成的API文档的数据)的路径;
    • 例如:guide文件夹中的api_data.json的绝对路径
  3. 修改target dir下配置文件(x-http-wrapper.json)中api_data.file_path_infos的配置信息,将api_data.json的绝对路径添加上去;
    "api_data": {     "source": "apidocjs",     "file_path_type": "file",     "file_path_infos": [       {         "os_name": "Mac OS X",         "path": "api_data.json的绝对路径"       },       {         "os_name": "Windows",         "path": "api_data.json的绝对路径"       }     ],     "file_charset": "UTF-8"   }复制代码
  4. 修改target dir中,API的模板文件中\\标签内,生成文件的目标路径;
    • API的模板文件是以.xhwt为后缀的文件,是生成各个http相关文件的模板;
    • \\标签内,保存的是模板文件生成文件的文件名称与文件地址;
      • 例如:
        {  "file_name":"HttpApi.swift",  "file_dirs":[      {          "os_name":"Windows",          "path":"生成文件的目标路径(绝对路径)"      },      {          "os_name":"Mac OS X",          "path":"生成文件的目标路径(绝对路径)"      }  ]}复制代码
  5. 修改target dir下配置文件(x-http-wrapper.json)中template_file_infos中的need_generate属性,用于开启、关闭生成文件的功能;
    • 例如:若你想生成HttpApi类型的文件,就需要将template_file_infos.HttpApi.need_generate设置为true,并要修改了xxx-httpapi.xhwt文件中header标签内的地址;
      "template_file_infos": {  "HttpApi": {    "need_generate": true,    "path": "ncm_ios_n-httpapi.xhwt"  },  ...}复制代码
  6. 命令行生成相关http文件
    • 命令行运行:java -jar (jar文件的路径) (配置文件的绝对路径)
    • jar文件的路径:在guide文件夹下有最新的jar(x-http-wrapper.jar)
    • 配置文件的绝对路径:配置文件(x-http-wrapper.json)的绝对路径
      java -jar x-http-wrapper.jar xxxx/x-http-wrapper.json复制代码

api的数据源:

  • api_data.json就是使用apidocjs工具生成的数据文件;

  1. 解析x-http-wrapper.json这个配置文件;
  2. 在配置文件中,有API数据文件(在api_data中),再根据配置数据,将API数据解析为x-http-wrapper中的model数据;
  3. 在配置文件中,有所有的x-http-wrapper的template文件(在template_file_infos中),根据template文件中的内容与model datas和配置一起,生成目标文件;

  1. 使用方式:
    java -jar x-http-wrapper.jar xxx/x-http-wrapper.json复制代码
  2. x-http-wrapper.json文件,必须是绝对路径,该文件是整个wrapper的配置文件;
  3. 若有多个json文件,也可以(如:有多个程序(ios,android)需要生成代码);

wrapper的配置文件:

  • 该文件保存有所有的配置信息, 共有8个分类:
    api_data, template_file_infos, base_config, filter, request, response, status_code, param_types

  1. BaseModel:
    • 所有的model都需要继承BaseModel
    • BaseModel中有一个泛型用于存储更高一级的BaseModel
    • 在template engine中,反射只认BaseModel,不是BaseModel的model不能反射
    • template engine在反射调用时,若没有在反射的对象中找到方法,会从higherLevel中去找,直到没有higherLevel为止;
  2. model的结构:
    • VersionModel-->StatusCodeGroup, RequestGroup
    • StatusCodeGroup-->StatusCode
    • RequestGroup-->Request-->Url,Header,Input,Response
    • Response-->Response File,Response Message

  1. 所有的类别都在XHWTFileType枚举中,现阶段共有6个类别;
    • HttpApi, Request, RequestParam, Response, StatusCode, BaseResponse
  2. 且在该枚举中也有该模板类别所需数据的获取过滤功能(getReflectiveDatas方法);

  1. 生成的文件内容由该文件类型获取到的API数据与标签两者来驱动
  2. 头部标签\\: 用于标示该模板文件,生成的目标文件路径和名称;
    • file_dirs:目标文件路径
    • file_name:目标文件名称
  3. 现阶段只有7个标签类型:使用反射来进行数据的加工
    • text, foreach, retain, list_single_line, if_else, list_replace, list_attach
    • 标签内部的匹配都为反射的方法名称;
      • 例如:在foreach标签中
        复制代码
        匹配的request_groups即为反射后去request_groups方法的数据,然后利用该数据去遍历;

转载地址:http://eojpl.baihongyu.com/

你可能感兴趣的文章
2017年物联网五大趋势
查看>>
Win10 S是Windows RT第二?微软:差别很大
查看>>
流量劫持已成行业毒瘤,不正当竞争当严惩
查看>>
《IPv6精髓(第2版)》——第1章 为何使用IPv61.1 IPv6历史
查看>>
最让程序员懊恼的 10 件事
查看>>
Iframe高度自适应(兼容IEFirefox、同域跨域)
查看>>
Google 工程师如何发现 Heartbleed 漏洞
查看>>
《Python面向对象编程指南》——2.8 __new__()方法和不可变对象
查看>>
ROS机器人程序设计(原书第2版)第1章 ROS Hydro系统入门
查看>>
《Android平板电脑开发秘籍》——3.9节技巧:创建一个下拉列表式的ActionBar
查看>>
《软件工程(第4版?修订版)》—第1章1.4节软件工程涉及的人员
查看>>
剖析一个java对象初始化顺序问题
查看>>
《Python和Pygame游戏开发指南》——1.7 安装Pygame
查看>>
reveal.js实现html播放ppt的炫酷效果
查看>>
《HTML5 canvas开发详解(第2版)》——2.12 检查一个点是否在当前路径
查看>>
《深入理解Scala》——第2章,第2.1节学习使用Scala交互模式(REPL)
查看>>
在Tableau中自定义版块地图
查看>>
《黑客秘笈——渗透测试实用指南(第2版)》—第2章2.1节被动信息搜索——开源情报(OSINT)...
查看>>
《21天学通HTML+CSS+JavaScript Web开发(第7版)》——1.7 作业
查看>>
微服务,微架构[一]之springboot[helloWorld]
查看>>