前言
在鸿蒙系统中进行网络请求是应用开发中的一个常见需求。本文将详细介绍如何使用自定义的MyHttpUtil类来简化HTTP请求的实现,并探讨其具体实现细节。MyHttpUtil是基于鸿蒙系统的ArkTS编写的一个实用工具类,可以有效地管理和发起HTTP请求。
1. 背景
在现代应用开发中,网络请求是必不可少的一部分。无论是获取远程数据还是提交用户信息,都需要通过HTTP请求与服务器进行通信。鸿蒙系统提供了强大的网络库,但直接使用这些库进行网络请求可能会显得繁琐且易出错。因此,封装一个通用的HTTP请求工具类可以大大简化开发过程。
2. MyHttpUtil类的实现
导入必要模块
首先,我们需要导入一些必要的模块,包括HTTP库、全局数据、偏好设置工具、日志工具、吐司工具等:
import http from '@ohos.net.http';
import GlobalData from '../global/GlobalData';
import PreferenceKey from '../preference/PreferenceKey';
import PreferencesUtil from '../preference/PreferencesUtil';
import DebugLogUtil, { LogStyle } from '../utils/DebugLogUtil';
import ToastUtils from '../utils/ToastUtils';
import HttpConnectAPI from './HttpConnectAPI';
定义请求方法和URL类型枚举
接下来,我们定义一些常用的请求方法和基础URL类型:
export enum RequestMethod {
OPTIONS = "OPTIONS",
GET = "GET",
HEAD = "HEAD",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
TRACE = "TRACE",
CONNECT = "CONNECT"
}
export enum BaseURLType {
COMMON,
SPECIAL
}
MyHttpUtil类的静态属性和方法
我们定义了静态属性和方法,用于配置和发起HTTP请求:
export class MyHttpUtil {
private static readonly LOG_TAG: string = "====MyHttpUtil====";
private static httpInstance = http.createHttp();
public static READ_TIME_OUT: number = 60000; // 单位:毫秒
public static CONNECT_TIME_OUT: number = 60000; // 单位:毫秒
public static async makeRequest(
url: string,
method: RequestMethod,
data: Record<string, number | string>,
mBaseURLType: BaseURLType,
showErrorToast: boolean = false,
successCallback: (result: Record<string, any>) => void,
errorCallback: (error: string) => void
): Promise<void> {
// 确保 URL 有效
if (!url) {
errorCallback('URL 不能为空');
return;
}
// 检查并获取用户的Token和OpenID
if (!GlobalData.getInstance().USER_INFO_TOKEN || !GlobalData.getInstance().USER_INFO_OPEN_ID) {
GlobalData.getInstance().USER_INFO_TOKEN = await PreferencesUtil.getInstance().get(PreferenceKey.USER_INFO_TOKEN_VALUE, '') as string;
GlobalData.getInstance().USER_INFO_OPEN_ID = await PreferencesUtil.getInstance().get(PreferenceKey.USER_INFO_OPEN_ID_VALUE, '') as string;
}
// 配置请求头
let mHeaderMap: Record<string, string> = {
'content-type': 'application/json;charset=UTF-8',
'connection': 'keep-alive',
'accessToken': GlobalData.getInstance().USER_INFO_TOKEN,
'openId': GlobalData.getInstance().USER_INFO_OPEN_ID,
'version': GlobalData.getInstance().API_VERSION
};
// 配置请求选项
let options: http.HttpRequestOptions = {
method: method,
header: mHeaderMap,
readTimeout: MyHttpUtil.READ_TIME_OUT,
connectTimeout: MyHttpUtil.CONNECT_TIME_OUT,
extraData: method !== RequestMethod.GET ? JSON.stringify(data) : undefined,
};
// 根据URL类型选择基础URL
switch (mBaseURLType) {
case BaseURLType.COMMON:
url = HttpConnectAPI.BaseIOVURL + url;
break;
case BaseURLType.SPECIAL:
break;
default:
url = HttpConnectAPI.BaseIOVURL + url;
}
// 处理GET请求的查询参数
if (method === RequestMethod.GET && Object.keys(data).length > 0) {
let queryString = Object.keys(data).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join('&');
url += `?${queryString}`;
}
try {
// 发起HTTP请求
let response: http.HttpResponse = await MyHttpUtil.httpInstance.request(url, options);
let result: Record<string, any> = JSON.parse(response.result.toString());
DebugLogUtil.log(LogStyle.LEVEL_DEBUG, MyHttpUtil.LOG_TAG, `url====${url}====method====${method}====header====${JSON.stringify(response.header)}====responseCode====${response.responseCode}`);
// 处理成功响应
if (response.responseCode === 200) {
DebugLogUtil.log(LogStyle.LEVEL_DEBUG, MyHttpUtil.LOG_TAG, `url====${url}====method====${method}====header====${JSON.stringify(response.header)}====responseCode====${response.responseCode}====Data====${JSON.stringify(result)}`);
successCallback(result);
} else {
// 处理错误响应
if (showErrorToast) {
ToastUtils.showToast('接口业务错误信息');
}
DebugLogUtil.log(LogStyle.LEVEL_ERROR, MyHttpUtil.LOG_TAG, `url====${url}====method====${method}====header====${JSON.stringify(response.header)}====ErrorResponseCode====${response.responseCode}`);
errorCallback(response.responseCode.toString());
}
} catch (error) {
// 处理请求异常
DebugLogUtil.log(LogStyle.LEVEL_ERROR, MyHttpUtil.LOG_TAG, `url====${url}====method====${method}====Exception====${error}`);
errorCallback(error);
}
}
}
3. 代码详解
导入必要模块:
我们首先导入了鸿蒙系统的HTTP库以及一些实用工具模块。
请求方法和URL类型枚举:
定义了HTTP请求的各种方法(如GET、POST等)和基础URL类型(COMMON和SPECIAL)。
静态属性和方法:
- LOG_TAG:用于日志记录的标签。
- httpInstance:创建一个HTTP实例用于发起请求。
- READ_TIME_OUT和CONNECT_TIME_OUT:配置请求的超时时间。
- makeRequest方法:核心方法,用于发起HTTP请求。
请求头和选项配置:
在makeRequest方法中,我们首先确保URL有效,然后检查用户的Token和OpenID,并配置请求头和选项。
基础URL选择:
根据不同的基础URL类型选择合适的URL。
处理GET请求的查询参数:
对于GET请求,我们将查询参数附加到URL上。
发起HTTP请求并处理响应:
使用httpInstance发起请求,并处理成功和失败的响应,进行日志记录和错误处理。
4. 使用示例
import http from '@ohos.net.http';
import GlobalData from '../global/GlobalData';
import PreferenceKey from '../preference/PreferenceKey';
import PreferencesUtil from '../preference/PreferencesUtil';
import DebugLogUtil, { LogStyle } from '../utils/DebugLogUtil';
import ToastUtils from '../utils/ToastUtils';
import HttpConnectAPI from './HttpConnectAPI';
export enum RequestMethod {
OPTIONS = "OPTIONS",
GET = "GET",
HEAD = "HEAD",
POST = "POST",
PUT = "PUT",
DELETE = "DELETE",
TRACE = "TRACE",
CONNECT = "CONNECT"
}
export enum BaseURLType {
COMMON,
SPECIAL
}
export class MyHttpUtil {
private static readonly LOG_TAG: string = "====MyHttpUtil====";
private static httpInstance = http.createHttp();
public static READ_TIME_OUT: number = 60 1000
public static CONNECT_TIME_OUT: number = 60 1000
public static async makeRequest(
url: string,
method: http.RequestMethod,
data: Record<string, number | string,
mBaseURLType: BaseURLType,
showErrorToast: boolean = false,
successCallback: (result: Record<string, Object) => void,
errorCallback: (error: string) => void
): Promise<void{
// 确保 URL 有效
if (!url) {
errorCallback('URL 不能为空');
return;
}
if(GlobalData.getInstance().USER_INFO_TOKEN == null || GlobalData.getInstance().USER_INFO_TOKEN.length == 0 || GlobalData.getInstance().USER_INFO_OPEN_ID == null || GlobalData.getInstance().USER_INFO_OPEN_ID.length == 0){
GlobalData.getInstance().USER_INFO_TOKEN = await PreferencesUtil.getInstance().get(PreferenceKey.USER_INFO_TOKEN_VALUE, '') as string
GlobalData.getInstance().USER_INFO_OPEN_ID = await PreferencesUtil.getInstance().get(PreferenceKey.USER_INFO_OPEN_ID_VALUE, '') as string
}
let mHeaderMap: Record<string, number | string= {
'content-type': 'application/json;charset=UTF-8',
'connection': 'keep-alive',
'accessToken': GlobalData.getInstance().USER_INFO_TOKEN,
'openId': GlobalData.getInstance().USER_INFO_OPEN_ID,
'version': GlobalData.getInstance().API_VERSION
};
let options: http.HttpRequestOptions = {
method: method,
header: mHeaderMap,
readTimeout: MyHttpUtil.READ_TIME_OUT,
connectTimeout: MyHttpUtil.CONNECT_TIME_OUT,
extraData: method != http.RequestMethod.GET ? JSON.stringify(data) : undefined, // 根据请求方法设置数据参数
};
switch (mBaseURLType) {
case BaseURLType.COMMON:
url = HttpConnectAPI.BaseIOVURL url
break;
case BaseURLType.SPECIAL:
url = url
break;
default:
url = HttpConnectAPI.BaseIOVURL url
}
// 如果是 GET 请求,并且有查询参数,则将查询参数附加到 URL 上
if (method === http.RequestMethod.GET && Object.keys(data).length 0) {
let queryString = Object.keys(data).map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`).join('&');
url += `?${queryString}`;
}
try {
// 使用同一个 http 实例发起请求
let response: http.HttpResponse = await MyHttpUtil.httpInstance.request(url, options);
let result:Record<string, Object= JSON.parse(response.result.toString());
DebugLogUtil.log(LogStyle.LEVEL_DEBUG, MyHttpUtil.LOG_TAG,'url====' url '====method====' method '====header====' JSON.stringify(response.header) '====responseCode====' response.responseCode);
// 处理成功响应
if (response.responseCode === 200) {
DebugLogUtil.log(LogStyle.LEVEL_DEBUG, MyHttpUtil.LOG_TAG,'url====' url '====method====' method '====header====' JSON.stringify(response.header) '====responseCode====' response.responseCode '====Data====' +JSON.stringify(result));
successCallback(result);
} else {
// 处理错误响应
if (showErrorToast) {
ToastUtils.showToast('接口业务错误信息');
}
DebugLogUtil.log(LogStyle.LEVEL_ERROR, MyHttpUtil.LOG_TAG,'url====' url '====method====' method '====header====' JSON.stringify(response.header) '====ErrorResponseCode====' response.responseCode);
errorCallback(response.responseCode.toString());
}
} catch (error) {
// 处理请求异常
DebugLogUtil.log(LogStyle.LEVEL_ERROR, MyHttpUtil.LOG_TAG,'url====' url '====method====' method '====Exception====' error);
errorCallback(error);
}
}
}
下面是一个使用MyHttpUtil类发起GET请求的示例:
async userLoginResult(userPhone: string, userPassword: string) {
let params: Record<string, number | string> = {
'phone': userPhone.toString(),
'password': passwordDigest.toString(),
};
await MyHttpUtil.makeRequest(HttpConnectAPI.API_USER_LOGIN, RequestMethod.GET, params, BaseURLType.COMMON, false,
async (result) => {
this.mLoginModelBean = JSON.parse(JSON.stringify(result))
}, (error) => {
this.mCustomDialogController.close()
ToastUtils.showToast($r('app.string.toast_login_page_content3'))
})
}
在这个示例中,我们调用了makeRequest方法,传入了请求的URL、方法、参数、URL类型和回调函数。
5. 总结
通过封装一个通用的HTTP请求工具类MyHttpUtil,我们可以在鸿蒙系统中更方便地进行网络请求。该工具类不仅简化了请求的配置和处理,还提供了日志记录和错误处理的功能,极大地提高了开发效率和代码的可维护性。