一、效果展示
通过在页面直接调用 userLogin(params) 方法,获取登录令牌
二、申请网络权限
访问网络时候首先需要申请网络权限,需要修改 src/main 目录下的 module.json5 文件,加入 requestPermissions 属性,详见官方文档
【声明权限】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/declare-permissions-V5
{
"module": {
// ...
"requestPermissions":[
{
"name" : "ohos.permission.INTERNET",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"inuse"
}
},
{
"name" : "ohos.permission.GET_NETWORK_INFO",
"usedScene": {
"abilities": [
"FormAbility"
],
"when":"inuse"
}
}
]
}
}
三、实现代码
共分为 7 个步骤,其中第 1、2、3、5 步都是创建基础实体,第 4 步为请求工具封装、第 6 步为API封装、第 7 步为页面调用测试,我会在最后贴上文件目录结构
1、创建常量类 CommonConstant.ets
在这个常量类中主要定义后端服务IP端口,以及一些需要使用的状态码信息
/**
* HTTP API
*/
export class Domain {
// 后端服务IP
static readonly SERVER: string = 'http://localhost:8999'
}
/**
* HTTP状态类
*/
export class HttpStatus {
// 成功
static readonly SUCCESS: number = 200
// 失败
static readonly ERROR: number = 500
}
export const enum ContentType {
// 响应体类型
JSON = 'application/json'
}
2、创建请求实体类 RequestBody.ets
这个请求实体类主要可以实现简单的传输【请求地址、请求方式、请求参数】这三个参数,再经过封装的工具去发送网络请求
export class RequestBody {
url: string;
method: string;
data: Object;
constructor() {
this.url = ''
this.method = 'GET'
this.data = new Object
}
}
3、创建响应实体类 ResponseResult.ets
这个响应实体主要对应后台的返回参数,比如我这里定义的后台响应码为【code】,信息为【msg】,响应数据为【data】,这个可以自行修改
export class ResponseResult {
code: number;
msg: string | Resource;
data: ArrayBuffer | Object | string
constructor() {
this.code = 0;
this.msg = '';
this.data = '';
}
}
4、创建请求工具类 HttpRequest.ets
详见官方文档
【HTTP数据请求】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/http-> request-V5
【异步并发概述 (Promise和async/await)】https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/async-concurrency-overview-V5#promise
// 这里需要引入第 2 步和第 3 步创建的请求和响应实体
import { ResponseResult } from '../response/ResponseResult'
import { RequestBody } from '../response/RequestBody'
// 这里需要引入第 1 步公共常量类
import { Domain, HttpStatus, ContentType } from '../constant/CommonConstant'
// 这里引用 HTTP 库
import http from '@ohos.net.http'
// HTTP响应处理时候需要的库
import { BusinessError } from '@kit.BasicServicesKit';
class HttpRequest {
request(requestBody: RequestBody) {
const promise: Promise<ResponseResult> = new Promise((resolve: Function, reject: Function) => {
console.log('创建HTTP请求,请求地址:' + Domain.SERVER + requestBody.url + ',请求方式:' + requestBody.method + ',请求体:' + JSON.stringify(requestBody.data))
// 创建HTTP请求
const httpRequest = http.createHttp()
// 在这里发送 HTTP 请求,并且需要设置Url、Header、Body等信息
httpRequest.request(
Domain.SERVER + requestBody.url,
{
method: isPost(requestBody.method) ? http.RequestMethod.POST : http.RequestMethod.GET,
readTimeout: 10000,
header: {
'Content-Type': ContentType.JSON
},
connectTimeout: 10000,
extraData: requestBody.data
},
(err: BusinessError, data: http.HttpResponse) => {
// 回调之后判断是否提示 Error
if (!err) {
let result = `${data.result}`
let resultJSON: ResponseResult = JSON.parse(result)
// 判断响应码是否成功
if (data.responseCode === HttpStatus.SUCCESS) {
if (resultJSON.code === 0) {
console.info('请求成功:' + resultJSON.data)
resolve(resultJSON)
} else {
reject(new Error('' + resultJSON.msg))
errorDialog('' + resultJSON.msg)
}
} else {
reject(new Error('' + resultJSON.msg))
errorDialog('' + resultJSON.msg)
}
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
} else {
console.error('ERROR:' + JSON.stringify(err));
if (err.code === 2300007) {
errorDialog('无法连接至服务器,请稍后重试')
}
if (err.code === 2300028) {
errorDialog('当前网络环境不稳定,请稍后重试')
}
// 当该请求使用完毕时,调用destroy方法主动销毁
httpRequest.destroy();
reject(new Error('当前网络环境不稳定,请稍后重试'))
}
}
)
})
return promise;
}
}
const httpRequest = new HttpRequest();
export default httpRequest as HttpRequest;
// 判断是否是GET方法
function isGet(method: string): boolean | undefined {
if (method === http.RequestMethod.GET) {
return true;
}
return false;
}
// 判断是否是POST方法
function isPost(method: string): boolean | undefined {
if (method === http.RequestMethod.POST) {
return true;
}
return false;
}
// 提示错误
function errorDialog(msg: string) {
console.error(msg)
}
5、创建一个用户登录实体 userInfo.ets
这个用户实体类包含用户的账号和密码信息,是登录所需
export class UserInfo {
account: string;
password: string;
constructor() {
this.account = ''
this.password = ''
}
}
6、创建一个用户API user.ets
这个API的作用就是统一格式,统一使用【url】、【data】、【method】这三个进行网络请求,也是在请求工具类 HttpRequest.ets 基础上的二次封装
// 这里引入第 4 步创建的请求工具类
import HttpRequest from '../request/HttpRequest'
// 这里引入第 3 步创建的响应体
import { ResponseResult } from '../response/ResponseResult'
// 这里引入第 5 步创建的自定义用户对象,主要用于定义各参数的类型
import { UserInfo } from '../../entity/userInfo'
// 用户登录 API
export function userLogin(params: UserInfo): Promise<ResponseResult> {
return HttpRequest.request({
url: '/auth/login',
data: params,
method:'POST'
})
}
7、在页面尝试调用 index.ets
最后在我们的页面启动时直接调用 user.ets 中的 userLogin 方法进行登录测试
// 这里需要引入第 6 步创建的用户API
import { userLogin } from '../common/api/user';
@Entry
@Component
struct Index {
// 在进入页面时调用 userLogin 接口进行测试
aboutToAppear(): void {
userLogin({account: 'admin', password: 'Admin@2024'}).then(res => {
console.info('页面成功获取到用户信息:' + res.data)
})
}
build() {
RelativeContainer() {
}
}
}
四、目录结构
总共 7 个步骤创建了 7 个文件,希望对您有所帮助