HarmonyOS HTTP网络请求(-)

Demo地址:https://gitee.com/hyhe/httpLibraryDemo.git
加解密、https认证在HarmonyOS HTTP网络请求(二)中做处理

一、框架说明

http请求框架说明.png

1. 功能说明

DecryptionResponseParam: 数据解密处理 待实现
EncryptionRequestParam: 数据加密处理 待实现
PrettyPrint: 日志打印处理
RequestApi: api列表
RequestAuthenHandler: 认证处理 待实现
RequestConfiguration: 配置RequestOption
HttpManager: 请求管理类
RequestImplement: 请求实现类
RequestMethod: 请求方法枚举
RequestOption: 自定义RequestOption类
RequestTools: http模块工具类
ResponseHandler: 请求结果处理类
ResponseModel: 最终返回业务层数据模型

二、核心类说明

1. 请求RequestOption类

export class RequestOption {
  /**
   * 请求host
   * 如果特定接口需要更换域名,请传入
   */
  host?: string;

  /**
   * url: 请求接口名
   */
  url?: string;

  /**
   * method: RequestMethod 请求方法
   */
  methodType?: RequestMethod;

  /**
   *
   * */
  header?: Record<string, any>;

  /**
   * queryParams: 请求参数
   */
  queryParams?: Record<string, any>;

  /**
   * Additional data of the request.
   * extraData: 当使用POST请求时此字段用于传递内容
   */
  extraData?: Record<string, any>;

  /**
   * encryptionParam: 加密后的参数
   */
  encryptionParam?: Record<string, any>;

  /**
   * expectDataType
   * 指定返回数据的类型。如果设置了此参数,系统将优先返回指定的类型
   */
  expectDataType?: http.HttpDataType = http.HttpDataType.OBJECT;

  /**
   * usingCache
   * 是否使用缓存,默认为true。
   * */
  usingCache?: boolean = false

  /**
   * priority
   * 优先级,范围[1,1000],默认是1
   * */
  priority?: number = 1

  /**
   * readTimeout
   * 读取超时时间。单位为毫秒(ms),默认为60000ms。
   * 设置为0表示不会出现超时情况
   * */
  readTimeout?: number = 60000

  /**
   * connectionTimeOut
   * 连接超时时间。单位为毫秒(ms),默认为60000ms
   * */
  connectionTimeOut?: number = 60000

  /**
   * usingProtocol
   * 使用协议。默认值由系统自动指定。
   * */
  usingProtocol?: http.HttpProtocol = http.HttpProtocol.HTTP1_1
}

2. RequestConfiguration

export class RequestConfiguration {
  static configurationRequestOptions(requestOption: RequestOption): Record<string, any> {

    return {
      url: requestOption.host + requestOption.url,
      method: requestOption.methodType, // 可选,默认为http.RequestMethod.GET
      // 开发者根据自身业务需要添加header字段
      header: this.dealHeader(requestOption.header),
      // query请求参数
      queryParams: this.dealParam(requestOption.queryParams),
      // 当使用POST请求时此字段用于传递内容
      extraData: this.dealExtraData(requestOption.extraData),
      encryptionParam: this.encryptionParam(requestOption.extraData),
      expectDataType: requestOption.expectDataType, // 可选,指定返回数据的类型
      usingCache: requestOption.usingCache, // 可选,默认为true
      priority: requestOption.priority, // 可选,默认为1
      readTimeout: requestOption.readTimeout, // 可选,默认为60000ms
      connectTimeout: requestOption.connectionTimeOut, // 可选,默认为60000ms
      usingProtocol: requestOption.usingProtocol, // 可选,协议类型默认值由系统自动指定
    };
  }

  static setCookie(): Record<string, any> {
    return []
  }

  static isValidUrl(): Boolean {
    return true
  }

  static dealHeader(header: Record<string, any>): Record<string, any> {
    var newHeader = header ?? {}
    newHeader["Content-Type"] = "application/json"
    return newHeader
  }

  static dealParam(param: Record<string, any>): Record<string, any> {
    var newParam = param ?? {}
    return newParam
  }

  static dealExtraData(extraData: Record<string, any>): Record<string, any> {
    var newExtraData = extraData ?? {}
    return newExtraData
  }

  static encryptionParam(extraParam: Record<string, any>): Record<string, any> {
    // 对参数进行加密处理
    return {}
  }
}

3. 网络请求方法枚举RequestMethod

export enum RequestMethod {
  GET = "GET",
  POST = "POST",
  OPTIONS = "OPTIONS",
  HEAD = "HEAD",
  PUT = "PUT",
  DELETE = "DELETE",
  TRACE = "TRANCE",
  CONNECT = "CONNECT"
}

4. 请求管理类 HttpManager

export class HttpManager {
  /**
   * 发送请求
   * @param RequestOptions
   * @return Promise
   */
  static requestApi<T>(requestOption: RequestOption): Promise<ResponseModel<T>> {
    // 网络请求中,可以在此处理requestOption
    return RequestImplement.requestApi<T>(requestOption);
  }
}

5. 实际请求类 RequestImplement

export class RequestImplement {
  static requestApi<T>(requestOption: RequestOption): Promise<ResponseModel<T>> {
    return new Promise<ResponseModel<T>>((resolve, reject) => {
      let resolveFunction = resolve;
      let rejectFunction = reject;

      // 每一个httpRequest对应一个HTTP请求任务,不可复用
      let httpRequest = http.createHttp();
      // 用于订阅HTTP响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
      // 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)。 8+
      httpRequest.on('headersReceive', (header) => {
        console.info('header: ' + JSON.stringify(header));
      });
      var resModel: ResponseModel<T>
      console.log(JSON.stringify(RequestConfiguration.configurationRequestOptions(requestOption)))
      let configuration = RequestConfiguration.configurationRequestOptions(requestOption)
      httpRequest.request(
        // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定
        configuration.url,
        configuration,
        (err, response) => {
          if (!err) {
            ResponseHandler.responseHandler<T>(configuration.url, response, (responseModel) => {
              resModel = responseModel as ResponseModel<T>
              if (responseModel.isSuccess) {
                resolveFunction(responseModel)
              } else {
                rejectFunction(responseModel)
              }
            })
          } else {
            console.info('error:' + JSON.stringify(err));
            // // 取消订阅HTTP响应头事件
            // httpRequest.off('headersReceive');
            // 当该请求使用完毕时,调用destroy方法主动销毁
            // httpRequest.destroy();
            resModel = new ResponseModel(err.message, err.code, false, "", null);
            resolveFunction(resModel)
          }
          PrettyPrint.printRequestLog(requestOption, resModel)
        });
    })
  }
}

6. 请求结果处理类 ResponseHandler

export class ResponseHandler {
  static responseHandler<T>(url: String, response: http.HttpResponse, reBackResponseModel: (responseModel: ResponseModel<T>) => void ): void {
    let responseModel: ResponseModel<T> = new ResponseModel("", 10000, false, "", null);
    // 需要处理Url
    if (url == "") {
      return
    }

    if (http.ResponseCode.OK == response.responseCode) {
      responseModel.data = JSON.stringify(response.result)
      console.log(`typeof=====${typeof response.result}`)
      let tModel: T = JSON.parse(JSON.stringify(response.result));
      if (tModel) {
        responseModel.msgCode = 200
        responseModel.isSuccess = true
        responseModel.resultModel = tModel
      } else {
        responseModel.msgCode = response.result["code"]
        responseModel.msg = response.result["message"]
      }
      reBackResponseModel(responseModel)
    } else {
      // 请求失败
      responseModel.msg = 'request fail'
      reBackResponseModel(responseModel)
    }
  }
}

7.请求结果处理后返回数据模型

export class ResponseModel<T> {
  msg?: string
  msgCode?: number
  isSuccess?: Boolean
  data?: string | Object | ArrayBuffer
  resultModel?: T

  constructor(msg: string = "", msgCode: number = 10000, isSuccess: Boolean = false, data: string = "", resultModel: T) {
    this.msg = msg
    this.msgCode = msgCode
    this.isSuccess = isSuccess
    this.data = data
    this.resultModel = resultModel
  }

  responseIsSuccess(): Boolean {
    return this.isSuccess ?? false
  }
}

8. 网络请求工具类

 /// 日志打印不全处理
  static printLongLog(message: string) {
    let maxLogSize = 400
    for (let i = 0; i < message.length / maxLogSize; i++) {
      let start = i * maxLogSize
      let end = (i + 1) * maxLogSize
      end = end > message.length ? message.length : end
      console.log(message.substring(start, end))
    }
  }
}

9. 请求日志打印类

export class PrettyPrint {
  static printRequestLog<T>(requestOption: RequestOption, responseModel: ResponseModel<T>) {
    console.log("");
    console.log(
      "࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ࿐₅₂ₒ");
    console.log("࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐ ------  请求开始  ------ ࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐");
    console.log("请求接口名:");
    console.log("url = " + requestOption.url);

    console.log("请求头参数:");
    console.log("headers = " + JSON.stringify(requestOption.header));

    console.log("初始参数:");
    console.log("incomeParam = " + JSON.stringify(requestOption.queryParams));
    console.log("incomeExtraData = " + JSON.stringify(requestOption.extraData));

    console.log("加密请求参数:");
    console.log("encryptionParam = " + JSON.stringify(requestOption.encryptionParam));

    if (responseModel?.isSuccess) {
      console.log("返回结果:");
      console.log("response = ")
      RequestTools.printLongLog(responseModel.data.toString())
    } else {
      console.log("失败日志:");
      console.log("errorInfo = " + responseModel?.msgCode + responseModel?.msg);
    }

    console.log("࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐ ------  请求结束  ------ ࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐࿐");
    console.log(
      "༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄༄");
  }
}

10. 本文以HAR模式实现

在index.ets中导出两个类

export { HttpManager } from './src/main/ets/http/RequestHttpManager'

export { RequestMethod } from './src/main/ets/http/RequestMethod'

三、请求示例

static getHomeAdvertisementData(reBack: (models: Array<CAHomeAdvModel>, error: BaseError) => void) {
// 配置请求参数
   let param: Record<string, string> = { "aa": "1", "bb": "0" }
          HttpManager.requestApi<ResultBaseModel<Array<CAHomeAdvModel>>>({
            host: "你的host: http://domain",
            url: "接口名",
            methodType: RequestMethod.POST,
            extraData: param
          }).then((responseModel) => {
            console.log("请求结果: " + JSON.stringify(responseModel))
          }).catch((error: BaseError) => {
            console.log("失败信息:" + JSON.stringify(error))
          })
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容