OpenHarmony开发者论坛
标题:
OpenHarmony_Http连接
[打印本页]
作者:
Laval社区小助手
时间:
2023-12-26 15:21
标题:
OpenHarmony_Http连接
[md]## 详情:[OpenHarmony_Http连接](
https://laval.csdn.net/64801fed9787b754b2643f01.html
)
## 概述
在OpenHarmony中,Http数据请求功能主要由ohos.net.http模块提供。使用该功能需要申请ohos.permission.INTERNET权限。
## Http接口简单介绍
| 模块/类 | 函数/方法 | 功能说明 |
| ------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ohos.net.http | function createHttp(): HttpRequest | 创建一个HttpRequest对象,该对象涵盖了发起/中断请求、订阅/取消Http响应头 事件等功能。每一个HttpRequest对象对应一个Http请求。如需发起多个Http请求,须为每个Http请求创建对应HttpRequest对象 |
| ohos.net.http.HttpRequest | on(type: "headersReceive", callback: AsyncCallback): void | 用于订阅http响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息。以callback方式进行异步回调 |
| ohos.net.http.HttpRequest | once(type: "headersReceive", callback: Callback): void | 用于订阅http响应头,但是只触发一次。一旦触发之后,订阅就会被移除。以callback方式进行异步回调 |
| ohos.net.http.HttpRequest | off(type: "headersReceive", callback: Callback): void | 取消对http响应头的监听。以callback方式进行异步回调 |
| ohos.net.http.HttpRequest | request(url: string, options: HttpRequestOptions, callback: AsyncCallback): void | 根据URL地址,发起一个GET请求。以callback方式进行异步回调 |
| ohos.net.http.HttpRequest | request(url: string, options: HttpRequestOptions, callback: AsyncCallback): void | 根据URL地址,采用不同方式(GET、POST等)发送请求,options中携带请求参数。以callback方式进行异步回调 |
| ohos.net.http.HttpRequest | request(url: string, options?: HttpRequestOptions: Promise | 根据URL地址,采用不同方式(GET、POST等)发送请求,options中携带请求参数(可选)。以Promise方式进行异步回调 |
## 开发步骤
* 导入@ohos.net.http模块。
* 创建HttpRequest对象。
* (可选)订阅HTTP响应头。
* 根据URL地址,设置请求参数,发起HTTP网络请求。
* (可选)处理HTTP响应头和HTTP网络请求的返回结果。
## Http连接示例
### 目标
使用http模块相关接口实现向服务端发送GET、POST、PUT、DELETE四种方式的请求
### 开发环境
示例开发环境:
```
IDE:DevEco Studio 3.0 Release(build:3.0.0.993)
SDK:Api Version9
开发模型:Stage
```
### 具体实现
#### 创建工程
打开DevEco Studio,创建SDK版本为API9、模型为Stage的OpenHarmony项目。
工程目录结构如下:
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony_Http%E8%BF%9E%E6%8E%A5/image/%E5%B7%A5%E7%A8%8B%E7%9B%AE%E5%BD%95.jpg?lastModify=1686118352)
![](
https://devpress.csdnimg.cn/d152170e86d94e2abf887baf2d79088e.jpg
)
#### 配置权限
在工程中的module.json5文件中配置ohos.permission.INTERNET 权限。
```
"abilities": [
{
...
...
}
],
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
```
#### 包装Http接口
在ets/service 目录下创建HttpService.ets文件。为了方便在UI页面中调用http模块相关功能,在该文件中创建HttpService类对Http模块相关接口进行封装。
HttService.ets:
```
import http from '@ohos.net.http';
import Logger from '../util/Logger'
const TAG="HttpDemo"
export class HttpService{
/**
* HttpRequest对象,承担了发起/取消、订阅响应事件的职责
*/
private httpClient:http.HttpRequest;
private requestMethodMap={
"GET":http.RequestMethod.GET,
"POST":http.RequestMethod.POST,
"PUT":http.RequestMethod.PUT,
"DELETE":http.RequestMethod.DELETE
}
constructor(){
this.createHttpRequest();
this.onHeaderReceive();
}
/**
* 创建HttpRequest对象,并赋值给httpClient
*/
private createHttpRequest(){
Logger.info(TAG,"start create HttpRequest");
this.httpClient=http.createHttp();
Logger.info(TAG,"create HttpRequest sucess ");
}
/**
* 销毁http连接,中断数据请求
*/
public destroy(){
this.httpClient.destroy();
Logger.info(TAG,"HttpRequest destroyed")
}
/**
* 用于订阅http响应头,此接口会比request请求先返回。可以根据业务需要订阅此消息
* 从API 8开始,使用on('headersReceive', Callback)替代on('headerReceive', AsyncCallback)
*/
private onHeaderReceive(){
this.httpClient.on("headersReceive",(data)=>{
Logger.info(TAG,"ResponseHeader:"+JSON.stringify(data));
})
}
/**
* 根据url和请求参数,向服务端发送http请求
* @param url
* @param param
*/
public requestHttp(url:string,param:RequestParam){
Logger.info(TAG,"start request:"+JSON.stringify(param));
let requestOption = {
method: this.requestMethodMap[param.method],
extraData: param.extraData,
header: param.header,
readTimeout: param.readTimeout,
connectTimeout: param.connectTimeout
}
Logger.info(TAG, "the request param is:" + JSON.stringify(requestOption));
this.httpClient.request(url,requestOption)
.then((httpResponse) => {
Logger.info(TAG, "send request sucess,the response is:" + JSON.stringify(httpResponse));
})
.catch((e) => {
Logger.info(TAG, "send request fail,the err is:" + JSON.stringify(e));
})
}
}
/**
* 请求参数接口
*/
export interface RequestParam {
method: string;
extraData?: string | Object | ArrayBuffer;
header?: Object; // default is 'content-type': 'application/json'
readTimeout?: number; // default is 60s
connectTimeout?: number; // default is 60s.
}
let httpService:HttpService=new HttpService();
export default httpService
```
#### 定义对话框组件
在ets/component目录下创建ReqParamDialog.ets文件,在该文件中定义用于设置请求参数的对话框。 完整代码如下:
```
@CustomDialog
@Component
export struct ReqParamDialog {
@State
list: number[] = [0];
flag: number = 0;
keys: string[] = [];
values: string[] = [];
setParamCallback: (keys: string[], values: string[]) => void;
dialogController: CustomDialogController;
build() {
Column() {
ForEach(this.list, (num) => {
Row() {
TextInput({ placeholder: "KEY:" })
.width(120)
.height(50)
.onChange((key) => {
this.keys[this.flag] = key;
})
Text(":")
.width(10)
.fontSize(16)
.fontColor(Color.Blue)
.textAlign(TextAlign.Center)
TextInput({ placeholder: "VALUE:" })
.height(50)
.onChange((value) => {
this.values[this.flag] = value;
})
}
}, num => num.toString())
Row() {
Button("新增")
.fontSize(25)
.onClick(() => {
this.flag++;
this.list.push(this.flag);
})
Button("减少")
.fontSize(25)
.onClick(() => {
if (this.list.length == 1) {
return;
}
this.list.splice(this.list.length - 1, 1);
})
Button("确认")
.fontSize(25)
.onClick(() => {
this.setParamCallback(this.keys, this.values);
this.dialogController.close();
})
Button("取消")
.fontSize(25)
.onClick(() => {
this.dialogController.close();
})
}
}
}
}
```
效果如下:
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony_Http%E8%BF%9E%E6%8E%A5/image/%E5%AF%B9%E8%AF%9D%E6%A1%86.jpg?lastModify=1686118352)
![](
https://devpress.csdnimg.cn/9c054f14cd9f415ab42392a71e3d69c9.jpg
)
#### 定义Http请求组件
在ets/component目录下创建HttpRequest.ets文件,在该文件中绘制http请求的UI界面。
* 定义选择http请求方法的菜单组件
```
...
...
@Component
export struct HttpRequest{
methods:string[]=["GET","POST","PUT","DELETE"];
...
...
@Builder
requestMethod() {
Flex({direction:FlexDirection.Column}) {
ForEach(this.methods,(method)=>{
Column(){
Text(method)
.fontSize(20)
.margin({bottom:1})
.onClick(()=>{
this.selectedMethod=method;
})
}
},method=>method)
}
}
...
...
}
```
* 组合菜单组件和对话框
将菜单组件绑定到显示请求方法的Text组件上。
```
build() {
...
Text(this.selectedMethod)//显示选择的Http请求方法
...
.bindMenu(this.requestMethod())
...
}
```
在HttpRequest组件中创建CustomDialogController对象,并将自定义对话框作为参数传入。
```
import httpService,{RequestParam} from '../service/HttpService'
import {ReqParamDialog} from '../component/ReqParamDialog'
@Component
export struct HttpRequest{
...
...
dialogController: CustomDialogController = new CustomDialogController({builder: ReqParamDialog({setParamCallback:this.setParamCallback.bind(this)}), autoCancel: true, alignment: DialogAlignment.Center })
...
...
}
build() {
...
...
}
...
}
```
HttpRequest.ets文件完整代码:
```
import httpService,{RequestParam} from '../service/HttpService'
import {ReqParamDialog} from '../component/ReqParamDialog'
@Component
export struct HttpRequest{
/**
* http请求方法的一个数组,用于生成选择菜单
*/
methods:string[]=["GET","POST","PUT","DELETE"];
/**
* 请求方法,默认为GET
*/
@State
selectedMethod:string="GET";
/**
* 请求地址,默认为
http://reqres.in/api/users?page=2
*/
url:string="http://reqres.in/api/users?page=2";
/**
* 请求参数
*/
requestParam:RequestParam=null;
/**
* 创建CustomDialogController,传入自定义对话框,控制对话框的显示和关闭
*/
dialogController: CustomDialogController = new CustomDialogController({builder: ReqParamDialog({setParamCallback:this.setParamCallback.bind(this)}), autoCancel: true, alignment: DialogAlignment.Center })
@Builder
requestMethod() {
Flex({direction:FlexDirection.Column}) {
ForEach(this.methods,(method)=>{
Column(){
Text(method)
.fontSize(20)
.margin({bottom:1})
.onClick(()=>{
this.selectedMethod=method;
})
}
},method=>method)
}
}
build() {
Column() {
Row(){
Text(this.selectedMethod)
.fontSize(25)
.align(Alignment.Center)
.border({width:1})
.bindMenu(this.requestMethod())
.width(100)
TextInput({placeholder:"http:"})
.onChange((url)=>{
this.url=url;
})
}
Row(){
Button("设置参数")
.fontSize(25)
.onClick(()=>{
this.dialogController.open();
})
}
.margin({top:5,bottom:10})
Button("发送请求")
.fontSize(25)
.onClick(()=>{
this.setParamIfNecessary();
httpService.requestHttp(this.url,this.requestParam);
this.resetRequestParam();
})
}
.width('100%')
.height('100%')
}
/**
* 请求发送完之后,重置参数
*/
resetRequestParam(){
this.requestParam=null;
}
/**
* 若没有给请求设置参数,则使用默认的参数
*/
setParamIfNecessary(){
if(this.requestParam==null){
this.requestParam={
method: this.selectedMethod,
header: {
'content-type': 'application/json'
},
readTimeout: 60000, // default is 60s
connectTimeout: 60000 // default is 60s.
}
}
}
/**
*传递给对话框的回调函数,将对话框输入的参数封装为对象
*/
setParamCallback(keys:string[],values:string[]){
let extraData=this.buildExtraData(keys,values);
this.requestParam = {
header: {
"content-type": "application/json"
},
method: this.selectedMethod,
extraData: extraData,
readTimeout: 60000, // default is 60s
connectTimeout: 60000 // default is 60s.
}
}
/**
* 封装请求参数为一个对象
*/
buildExtraData(keys:string[],values:string[]){
let extraData={};
for(let i=0;i<keys.length;i++){
extraData[keys
]=values
;
}
return extraData;
}
}
```
#### 创建入口页面
在ets/pages目录下创建index.ets文件。在该文件中导入HttpRequest.ets组件创建程序的入口页面。
```
import {HttpRequest} from '../component/HttpRequest'
@Entry
@Component
struct Index {
build() {
Column(){
HttpRequest()
}
}
}
```
页面最终效果预览:
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony_Http%E8%BF%9E%E6%8E%A5/image/%E8%AF%B7%E6%B1%82%E7%95%8C%E9%9D%A2%E9%A2%84%E8%A7%88.jpg?lastModify=1686118352)
![](
https://devpress.csdnimg.cn/ba97f79f37b141959eabf3bb38727e56.jpg
)
#### 测试结果
开发板型号:WAGNER
OH版本:3.2.5.5
**发送GET请求**
测试的url: [
https://reqres.in/api/users?page=2
](
https://reqres.in/api/users?page=2&login=from_csdn
)
日志打印:
```
//响应头信息:
08-03 16:52:33.702 6439 6439 I 02200/JsApp: HttpDemo: ResponseHeader:{"access-control-allow-origin":"*","age":"1998","cache-control":"max-age=14400","cf-cache-status":"HIT","cf-ray":"734dd15b999e7da
c-LAX","connection":"keep-alive","content-encoding":"gzip","content-type":"application/json; charset=utf-8","date":"Wed, 03 Aug 2022 08:52:33 GMT","etag":"W/\"406-ut0vzoCuidvyMf8arZpMpJ6ZRDw\"","expec
t-ct":"max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"","expires":"Wed, 03 Aug 2022 09:52:32 GMT","location":"https://reqres.in/api/users?page=2","nel":"{\"su
ccess_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}","report-to":"{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=65aGmR0ar0fCc%2BGz5YrBCPBBUwmzeA%2BDUDIEiePrK2
XvwICV9KBBBuj0vIxq4RP0G7%2F%2BKwhOuR8d8PnT1IEIqpStt2taYJ%2F%2B3fj4JjxjU2Sddgys%2FCMVtQSJW7qtbfT8MnZq3asH4A%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","server":"cloudflare","transfer-encoding"
:"chunked","vary":"Accept-Encoding","via":"1.1 vegur","x-powered-by":
08-03 16:52:33.702 6439 6439 I 02200/JsApp: HttpDemo: send request sucess
//响应内容
08-03 16:52:33.702 6439 6439 I 02200/JsApp: HttpDemo: the result is:{code:200,data:{"page":2,"per_page":6,"total":12,"total_pages":2,"data":[{"id":7,"email":"michael.lawson@reqres.in","first_name":"
Michael","last_name":"Lawson","avatar":"https://reqres.in/img/faces/7-image.jpg"},{"id":8,"email":"lindsay.ferguson@reqres.in","first_name":"Lindsay","last_name":"Ferguson","avatar":"https://reqres.in
/img/faces/8-image.jpg"},{"id":9,"email":"tobias.funke@reqres.in","first_name":"Tobias","last_name":"Funke","avatar":"https://reqres.in/img/faces/9-image.jpg"},{"id":10,"email":"byron.fields@reqres.in
","first_name":"Byron","last_name":"Fields","avatar":"https://reqres.in/img/faces/10-image.jpg"},{"id":11,"email":"george.edwards@reqres.in","first_name":"George","last_name":"Edwards","avatar":"https
://reqres.in/img/faces/11-image.jpg"},{"id":12,"email":"rachel.howell@reqres.in","first_name":"Rachel","last_name":"Howell","avatar":"https://reqres.in/img/faces/12-image.jpg"}],"support":{"url":"http
s://reqres.in/#support-heading","text":"To keep ReqRes free, contribu
```
**发送POST请求**
测试的url: [
https://reqres.in/api/users
](
https://reqres.in/api/users?login=from_csdn
) 参数:
```
{
"name":"morpheus",
"job":"leader"
}
```
日志打印:
```
//响应头信息:
08-03 17:00:17.796 6439 6439 I 02200/JsApp: HttpDemo: ResponseHeader:{"access-control-allow-origin":"*","cache-control":"max-age=3600","cf-cache-status":"DYNAMIC","cf-ray":"734ddcb00acf5281-LAX","co
nnection":"keep-alive","content-length":"51","content-type":"application/json; charset=utf-8","date":"Wed, 03 Aug 2022 09:00:17 GMT","etag":"W/\"33-wOvBK8Nue+Ck3OlpSqu8QL5bQlI\"","expect-ct":"max-age=
604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"","expires":"Wed, 03 Aug 2022 10:00:16 GMT","location":"https://reqres.in/api/users","nel":"{\"success_fraction\":0,\"r
eport_to\":\"cf-nel\",\"max_age\":604800}","report-to":"{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=096ZxRLklCMfXbATfkCIKKHVMpSiEnPqDsg%2FH6qZzSkV9SsgEZGbr%2BiPJEqvIjbK
q0vUdmSf66q2gl8Tb14tgNp6b1TEbf%2Fg1IJVOZNNYi5m5Wb%2FaXUjCc4wXFVdXnLg8Uojxk7DPg%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","server":"cloudflare","transfer-encoding":"chunked","vary":"Accept-En
coding","via":"1.1 vegur","x-powered-by":"Express"}
08-03 17:00:17.796 6439 6439 I 02200/JsApp: HttpDemo: send request sucess
//响应内容
08-03 17:00:17.796 6439 6439 I 02200/JsApp: HttpDemo: the result is:{code:201,data:{"id":"846","createdAt":"2022-08-03T09:00:17.537Z"}}
```
**发送PUT请求**
测试的url: [
https://reqres.in/api/users/2
](
https://reqres.in/api/users/2?login=from_csdn
)
参数:
```
{
"name":"morpheus",
"job":"zion resident"
}
```
日志打印:
```
//响应头信息:
08-03 17:02:00.411 6439 6439 I 02200/JsApp: HttpDemo: ResponseHeader:{"access-control-allow-origin":"*","cache-control":"max-age=3600","cf-cache-status":"DYNAMIC","cf-ray":"734ddf30ed467add-LAX","co
nnection":"keep-alive","content-length":"40","content-type":"application/json; charset=utf-8","date":"Wed, 03 Aug 2022 09:02:00 GMT","etag":"W/\"28-3PvShaMs/ugdjKvpR1lS0+UyqjQ\"","expect-ct":"max-age=
604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\"","expires":"Wed, 03 Aug 2022 10:01:58 GMT","location":"https://reqres.in/api/users/2","nel":"{\"success_fraction\":0,\
"report_to\":\"cf-nel\",\"max_age\":604800}","report-to":"{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=409PQEWa3s3L1hO7EGdMvoi19ChvQfyhXJWmwspO79yOYiLOA665haY9mse4apGcNj
uLo8JHCEsRDPrNk0UUqiIYOn4d5t7AF4ewaet5QVxCsB%2Fx%2BG6fzQgRtU0A0ZdkNvqZU2QDrA%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","server":"cloudflare","transfer-encoding":"chunked","vary":"Accept-Enco
ding","via":"1.1 vegur","x-powered-by":"Express"}
08-03 17:02:00.412 6439 6439 I 02200/JsApp: HttpDemo: send request sucess
//响应内容
08-03 17:02:00.412 6439 6439 I 02200/JsApp: HttpDemo: the result is:{code:200,data:{"updatedAt":"2022-08-03T09:02:00.068Z"}}
```
**发送DELETE请求**
测试的url: [
https://reqres.in/api/users/2
](
https://reqres.in/api/users/2?login=from_csdn
)
日志打印:
```
//响应头信息:
08-03 17:02:55.093 6439 6439 I 02200/JsApp: HttpDemo: ResponseHeader:{"access-control-allow-origin":"*","cache-control":"max-age=3600","cf-cache-status":"DYNAMIC","cf-ray":"734de0865f4e7e1c-LAX","co
nnection":"keep-alive","date":"Wed, 03 Aug 2022 09:02:54 GMT","etag":"W/\"2-vyGp6PvFo4RvsFtPoIWeCReyIC8\"","expect-ct":"max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/ex
pect-ct\"","expires":"Wed, 03 Aug 2022 10:02:53 GMT","location":"https://reqres.in/api/users/2","nel":"{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}","report-to":"{\"endpoints\"
:[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=N66IndbYWWvUovc%2Bp4irrFXzr%2Bf3cV5xwgz9MPbv49eVZpF9tPWeKBFr4UbgMNmGQ1kRb8DoiqpcG81GD%2FrzhzH818MBCVT1BrZ1iYXyocny1lVyBBN5CuI5%2Bzc5vwCGHp
m0HqnvLw%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}","server":"cloudflare","transfer-encoding":"chunked","vary":"Accept-Encoding","via":"1.1 vegur","x-powered-by":"Express"}
08-03 17:02:55.093 6439 6439 I 02200/JsApp: HttpDemo: send request sucess
//响应内容
08-03 17:02:55.093 6439 6439 I 02200/JsApp: HttpDemo: the result is:{code:204,data:}
```
## 参考文献
[1] 应用权限列表. [
https://gitee.com/openharmony/do ... /permission-list.md
](
https://gitee.com/openharmony/do ... .md?login=from_csdn
)
[2] 使用ArkTS语言开发(Stage模型). [
https://gitee.com/openharmony/do ... t-with-ets-stage.md
](
https://gitee.com/openharmony/do ... .md?login=from_csdn
)
[3] Http数据请求. [
https://gitee.com/openharmony/do ... ity/http-request.md
](
https://gitee.com/openharmony/do ... .md?login=from_csdn
)
[4] Http接口介绍. [
https://gitee.com/openharmony/do ... pis/js-apis-http.md
](
https://gitee.com/openharmony/do ... .md?login=from_csdn
)
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5