赞
踩
在HarmonyOS应用开发中,通过HTTP访问网络,可以使用官方提供的@ohos.net.http模块。但是官方提供的直接使用不太好使用,需要封装下才好。这里采用TS的装饰器实现AOP效果 完成前后端接口风格的统一
文档中心:@ohos.net.http (数据请求)
TS装饰器介绍:TypeScript装饰器
实现效果:
// 引入包名 import http from '@ohos.net.http'; // 每一个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)); }); httpRequest.request( // 填写HTTP请求的URL地址,可以带参数也可以不带参数。URL地址需要开发者自定义。请求的参数可以在extraData中指定 "EXAMPLE_URL", { method: http.RequestMethod.POST, // 可选,默认为http.RequestMethod.GET // 开发者根据自身业务需要添加header字段 header: { 'Content-Type': 'application/json' }, // 当使用POST请求时此字段用于传递内容 extraData: { "data": "data to send", }, expectDataType: http.HttpDataType.STRING, // 可选,指定返回数据的类型 usingCache: true, // 可选,默认为true priority: 1, // 可选,默认为1 connectTimeout: 60000, // 可选,默认为60000ms readTimeout: 60000, // 可选,默认为60000ms usingProtocol: http.HttpProtocol.HTTP1_1, // 可选,协议类型默认值由系统自动指定 }, (err, data) => { if (!err) { // data.result为HTTP响应内容,可根据业务需要进行解析 console.info('Result:' + JSON.stringify(data.result)); console.info('code:' + JSON.stringify(data.responseCode)); // data.header为HTTP响应头,可根据业务需要进行解析 console.info('header:' + JSON.stringify(data.header)); console.info('cookies:' + JSON.stringify(data.cookies)); // 8+ // 取消订阅HTTP响应头事件 httpRequest.off('headersReceive'); // 当该请求使用完毕时,调用destroy方法主动销毁 httpRequest.destroy(); } else { console.info('error:' + JSON.stringify(err)); // 取消订阅HTTP响应头事件 httpRequest.off('headersReceive'); // 当该请求使用完毕时,调用destroy方法主动销毁。 httpRequest.destroy(); } } );
使用Stage模型的应用,需要在module.json5配置文件中声明权限。
{
"module" : {
"requestPermissions":[
{
"name": "ohos.permission.INTERNET"
}
]
}
}
export class ApiResult {
code : string
msg ?: string
data ?: any
}
/** * <pre> * @desc : 网络请求配置 * </pre> */ export interface RequestOptions { /** * Request url. */ url?: string; /** * Request method. */ method?: RequestMethod; // default is GET /** * Additional data of the request. * extraData can be a string or an Object (API 6) or an ArrayBuffer(API 8). */ extraData?: string | Object | ArrayBuffer; /** * Request url queryParams . */ queryParams ?: Record<string, string>; /** * HTTP request header. */ header?: Object; // default is 'content-type': 'application/json' } export enum RequestMethod { OPTIONS = "OPTIONS", GET = "GET", HEAD = "HEAD", POST = "POST", PUT = "PUT", DELETE = "DELETE", TRACE = "TRACE", CONNECT = "CONNECT" }
import http from '@ohos.net.http'; import { RequestOptions } from './RequestOptions'; import { ApiResult } from '../ApiResult/ApiResult'; // 引入弹窗 import PreferenceUtil from '../../utils/PreferenceUtil' import promptAction from '@ohos.promptAction'; import { LoadingProgressDialog } from '../../utils/LoadingProgressDialog'; import router from '@ohos.router'; /** * Http请求器 */ export class HttpCore { loadingDialog: CustomDialogController = new CustomDialogController({ builder: LoadingProgressDialog(), alignment:DialogAlignment.Center, autoCancel: true, customStyle: true }); /** * 发送请求 * @param requestOption * @returns Promise */ request(requestOptions: RequestOptions): Promise<ApiResult> { let p = new Promise<ApiResult>(async (resolve, reject) => { // 每一个httpRequest对应一个HTTP请求任务,不可复用 let httpRequest = http.createHttp(); let token : string = await getToken(); let promise = httpRequest.request(requestOptions.url, { method: requestOptions.method, connectTimeout: 60000, readTimeout: 60000, header:{ 'Content-Type': 'application/json', 'token': token, 'client_type': 'HarmonyOS' }, extraData: requestOptions.extraData }); promise.then((data) => { //TODO:此处补充数据拆包的操作 let resultObj = JSON.parse(data.result.toString()); //弹窗提示接口返回msg setTimeout(() => { promptAction.showToast({ message: resultObj.msg }) }, 500); //如果业务码为20000 则返回ApiReslut if (resultObj.code == 20000) { console.log(JSON.stringify(resultObj)) resolve(resultObj); } if (resultObj.code == 0){ router.replaceUrl({ url: "pages/MainPage/Login" }).then(() => { console.log('router successful') }).catch(err => { console.log('router err') }) } //如果返回数据包含token信息 则刷新token if (resultObj.token != undefined) { PreferenceUtil.putPreference('token',resultObj.token) } }).catch((err) => { //这里做全局异常统一处理 根据Http状态码做出处理 console.info('error:' + JSON.stringify(err)); reject(err); }); httpRequest.destroy(); }) return p; } } async function getToken(): Promise<string> { return new Promise<string>(async (resolve, reject) => { try { const data = await PreferenceUtil.getPreference('token'); if (typeof data === 'string') { resolve(data); } else { reject(new Error('Invalid token')); } } catch (err) { reject(err); } }); } export const httpCore = new HttpCore();
import { RequestMethod, RequestOptions } from './RequestOptions'; import { httpCore } from './HttpCore'; import { ApiResult } from '../ApiResult/ApiResult'; /** * <pre> * @desc : 对外工具包 * </pre> */ export class HttpUtil { private static mInstance: HttpUtil; // 防止实例化 private constructor() { } static getInstance(): HttpUtil { if (!HttpUtil.mInstance) { HttpUtil.mInstance = new HttpUtil(); } return HttpUtil.mInstance; } request (option: RequestOptions): Promise<ApiResult> { return httpCore.request(option); } /** * 封装Post网络请求 * @param option * @returns */ Post(option:RequestOptions){ if(option != null){ option.method = RequestMethod.POST } return this.request(option); } /** * 封装Get网络请求 * @param option * @returns */ Get(option:RequestOptions){ if(option != null){ option.method = RequestMethod.GET } return this.request(option); } } export const httpUtil = HttpUtil.getInstance();
import { ApiResult } from '../ApiResult/ApiResult'; import { httpUtil } from '../Http/HttpUtil'; import { RequestOptions } from '../Http/RequestOptions'; /** * 利用Map保存参数和值的映射关系 为避免参数名及方法名重复 采用组合Key的方法 */ type FunParamMapKey = { target: Object; //所在类 methodName: string; //所在方法 index: number; //参数名索引值 } let funParamMap = new Map<string, string>(); // @Get注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行网络请求 //Get 需要拼接URl export function Get(url: string) { return function (target: any, methodName: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; let URL: string = url; let options: RequestOptions = { url: URL, queryParams: {} }; descriptor.value = async function (...args: any[]) { //对于方法中的每一个(methodName,arg)遍历加入到网络请求配置中 args.forEach((arg, index) => { // 通过已知的信息构造组合Key对象 let obj: FunParamMapKey = { target: target, methodName: methodName, index: index }; // 通过组合Key(通过对内容的比较而不是值 节省内存)从内存map中获取@Param修饰的内容 let paramName = funParamMap[JSON.stringify(obj)]; // 将正确的参数名及值添加至网络请求参数中 if (typeof paramName !== 'undefined') { if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer || typeof arg === 'number') { options.queryParams[paramName] = arg } else { console.log('参数类型不对') throw new Error(`Invalid parameter type at index ${index}.`); } } }); //拼接请求参数 const urlParams = Object.keys(options.queryParams).map(key => `${key}=${options.queryParams[key]}`).join('&') console.log('urlParams:', urlParams) if (URL.includes("?")) { options.url = `${URL}${urlParams}` } else { options.url = `${URL}?${urlParams}` } const p = new Promise<ApiResult>((resolve, reject) => { httpUtil.Get(options).then((response) => { const result: ApiResult = response; resolve(result); }).catch((error) => { reject(error); }); }); return await p; }; }; } // @Post注解 拿到url 从函数的@Param拿到参数名及参数值 利用HttpUtil进行Post网络请求 export function Post(url: string) { return function (target: any, methodName: string, descriptor: PropertyDescriptor) { const originalMethod = descriptor.value; let options: RequestOptions = { url: url, extraData: {} }; descriptor.value = async function (...args: any[]) { //对于方法中的每一个(methodName,arg)遍历加入到网络请求配置中 args.forEach((arg, index) => { console.log("参数值",JSON.stringify(arg)) // 通过已知的信息构造组合Key对象 let obj: FunParamMapKey = { target: target, methodName: methodName, index: index }; // 通过组合Key(通过对内容的比较而不是值 节省内存)从内存map中获取@Param修饰的内容 let paramName = funParamMap[JSON.stringify(obj)]; console.log("参数名:",paramName) // 将正确的参数名及值添加至网络请求参数中 if (typeof paramName !== 'undefined') { if (typeof arg === 'string' || typeof arg === 'object' || arg instanceof ArrayBuffer) { options.extraData[paramName] = arg; } else { throw new Error(`Invalid parameter type at index ${index}.`); } }else { //如果获取不到形参名 及未被@Param标记 并且参数的类型是对象 if (typeof arg === 'object') { options.extraData = JSON.stringify(arg) } } }); console.log('extraData', JSON.stringify(options.extraData)) const p = new Promise<ApiResult>((resolve, reject) => { httpUtil.Post(options).then((response) => { const result: ApiResult = response; resolve(result); }).catch((error) => { reject(error); }); }); return await p; }; }; } /** * @Param 注解将想要获取的Param添加至内存Map中 * @param paramName * @returns */ export function Param(paramName: string) { return function (target: any, methodName: string, parameterIndex: number) { let obj: FunParamMapKey = { target: target, methodName: methodName, index: parameterIndex }; funParamMap[JSON.stringify(obj)] = paramName; }; }
import { UserEditModel } from '../models/UserEditModel'; import{Post,Get, Param} from './aop/aop' import { ApiResult } from './ApiResult/ApiResult'; export class UserApi { /** * 根据用户ID查询用户 * @param @Param("userId") userId * @returns */ @Get("http://localhost:8080/api/user/get") getUser(@Param("userId") userId: Number):Promise<ApiResult> { return } /** * 获取所有用户 * @returns */ @Get("http://localhost:8080/api/user/getAllUser") getAllUser():Promise<ApiResult> { return } /** * 更新用户信息 * @returns */ @Post("http://localhost:8080/api/user/update") updateUser( user : UserEditModel):Promise<ApiResult> { return } } export const userApi = new UserApi();
userApi.getAllUser().then((apiResult)=>{
this.userList = apiResult.data
})
//TODO 加载用户信息
userApi.getUser(Number(this.userID)).then((apiResult)=>{
this.user = apiResult.data
})
gitee项目:鸿蒙前端 简易RBAC管控界面
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。