1. HTTP協(xié)議簡介
HTTP(Hypertext Transfer Protocol)協(xié)議是現(xiàn)代互聯(lián)網(wǎng)的基石協(xié)議之一,有著最廣泛的應(yīng)用,于1991年由英國計(jì)算機(jī)科學(xué)家蒂姆·伯納斯·李(Tim Berners-Lee)正式提出,當(dāng)時(shí)被稱為HTTP協(xié)議0.9版本;1996年通過RFC 1945發(fā)布了1.0版本,當(dāng)然,這些都不是正式的Internet標(biāo)準(zhǔn),第一個(gè)正式的HTTP協(xié)議標(biāo)準(zhǔn)是1.1版本,于1997年1月通過RFC 2068發(fā)布,然后又于2015年5月通過RFC 7540正式發(fā)布了HTTP/2標(biāo)準(zhǔn),最新的標(biāo)準(zhǔn)是HTTP/3,通過2022年6月6日的RFC 9114正式發(fā)布。
鴻蒙API內(nèi)置了對(duì)HTTP協(xié)議客戶端的支持,遺憾的是目前(API 9,包括API 10、11)還不支持服務(wù)端(倒是可以在API 10或更高版本中通過TCP Server自行實(shí)現(xiàn)一個(gè)),本文將講解HTTP客戶端相關(guān)方法的使用。
2. HttpRequest的常用方法
鴻蒙封裝的HTTP操作類位于模塊http中,使用如下的方式導(dǎo)入:
import http from '@ohos.net.http';
http模塊包括多個(gè)http請求相關(guān)方法,就本文而言,重點(diǎn)需要掌握的是如下兩個(gè):
1)createHttp(): HttpRequest
創(chuàng)建一個(gè)HttpRequest對(duì)象,每一個(gè)HTTP請求都需要有一個(gè)獨(dú)立的HttpRequest對(duì)象,多個(gè)請求就要?jiǎng)?chuàng)建多個(gè)對(duì)象,最多創(chuàng)建100個(gè)。
2)request(url: string, options? : HttpRequestOptions): Promise<HttpResponse>
根據(jù)URL地址,發(fā)起HTTP網(wǎng)絡(luò)請求,使用Promise方式作為異步方法,其中參數(shù)url為發(fā)起網(wǎng)絡(luò)請求的URL地址,options為發(fā)起請求的可選參數(shù),包括請求的方法、額外數(shù)據(jù)、希望的返回值類型、請求頭等信息,詳細(xì)的可以參考官方文檔。
3. HTTP模擬登錄示例
為演示HTTP模擬登錄,假設(shè)我們有這樣一個(gè)網(wǎng)站,訪問該網(wǎng)站時(shí)如果沒有登錄,會(huì)被重定向到登錄頁面,如圖所示:

如果成功登錄后,會(huì)重定向到首頁,如圖所示,這里會(huì)出現(xiàn)下載列表:

我們要實(shí)現(xiàn)的示例就是模擬這個(gè)登錄過程,從而可以得到首頁登錄后的內(nèi)容。
本示例運(yùn)行后的頁面如圖所示:

單擊“請求”按鈕可以模擬沒有登錄直接訪問首頁的情況,單擊“登錄”按鈕就是模擬登錄,
下面詳細(xì)介紹創(chuàng)建該應(yīng)用的步驟。
步驟1:創(chuàng)建Empty Ability項(xiàng)目。
步驟2:在module.json5配置文件加上對(duì)權(quán)限的聲明:
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
這里添加了訪問互聯(lián)網(wǎng)的權(quán)限。
步驟3:在Index.ets文件里添加如下的代碼:
import http from '@ohos.net.http';
import util from '@ohos.util';
@Entry
@Component
struct Index {
//連接、通訊歷史記錄
@State msgHistory: string = ''
//首頁地址
@State homePageUrl: string = "http://192.168.100.100:8081/index"
//登錄地址
@State loginUrl: string = "http://192.168.100.100:8081/auth"
//用戶名
@State loginName: string = "zhanglei"
//密碼
@State passwd: string = "cangjie"
scroller: Scroller = new Scroller()
build() {
Row() {
Column() {
Text("模擬登錄示例")
.fontSize(14)
.fontWeight(FontWeight.Bold)
.width('100%')
.textAlign(TextAlign.Center)
.padding(10)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Text("首頁地址:")
.fontSize(14)
.width(80)
.flexGrow(0)
TextInput({ text: this.homePageUrl })
.onChange((value) => {
this.homePageUrl = value
})
.width(110)
.fontSize(11)
.flexGrow(1)
Button("請求")
.onClick(() => {
this.requestHomePage()
})
.width(70)
.fontSize(14)
.flexGrow(0)
}
.width('100%')
.padding(10)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Text("用戶名:")
.fontSize(14)
.width(80)
.flexGrow(0)
TextInput({ text: this.loginName })
.onChange((value) => {
this.loginName = value
})
.width(110)
.fontSize(11)
.flexGrow(1)
Text("密碼:")
.fontSize(14)
.width(60)
.flexGrow(0)
TextInput({ text: this.passwd })
.onChange((value) => {
this.passwd = value
})
.type(InputType.Password)
.width(100)
.fontSize(11)
.flexGrow(1)
}
.width('100%')
.padding(10)
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
Text("登錄地址:")
.fontSize(14)
.width(80)
.flexGrow(0)
TextInput({ text: this.loginUrl })
.onChange((value) => {
this.loginUrl = value
})
.width(100)
.fontSize(11)
.flexGrow(1)
Button("登錄")
.onClick(() => {
this.login()
})
.width(70)
.fontSize(14)
.flexGrow(0)
}
.width('100%')
.padding(10)
Scroll(this.scroller) {
Text(this.msgHistory)
.textAlign(TextAlign.Start)
.padding(10)
.width('100%')
.backgroundColor(0xeeeeee)
}
.align(Alignment.Top)
.backgroundColor(0xeeeeee)
.height(300)
.flexGrow(1)
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.On)
.scrollBarWidth(20)
}
.width('100%')
.justifyContent(FlexAlign.Start)
.height('100%')
}
.height('100%')
}
//請求首頁
requestHomePage() {
//http請求對(duì)象
let httpRequest = http.createHttp();
httpRequest.request(this.homePageUrl)
.then((resp) => {
this.msgHistory += "響應(yīng)碼:" + resp.responseCode + "\r\n"
this.msgHistory += resp.result + "\r\n"
})
.catch((e) => {
this.msgHistory += "請求失?。? + e.message + "\r\n"
})
}
//模擬登錄
login() {
//http請求對(duì)象
let httpRequest = http.createHttp();
//請求的登錄名和密碼參數(shù)
let params = "username=" + this.loginName + "&password=" + this.passwd
let opt: http.HttpRequestOptions = {
method: http.RequestMethod.POST,
extraData: params,
header: {'Content-Type': 'application/x-www-form-urlencoded' },
expectDataType: http.HttpDataType.STRING
}
httpRequest.request(this.loginUrl, opt)
.then((resp) => {
this.msgHistory += "響應(yīng)碼:" + resp.responseCode + "\r\n"
this.msgHistory += resp.result + "\r\n"
})
.catch((e) => {
this.msgHistory += "請求失?。? + e.message + "\r\n"
})
}
}
步驟4:編譯運(yùn)行,可以使用模擬器或者真機(jī)。
步驟5:配置網(wǎng)站首頁地址和登錄地址,然后單擊“請求”按鈕,頁面如圖所示:

可以看到,被重定向到了登錄頁面。
然后單擊“登錄”按鈕,界面如圖所示:

此時(shí)已經(jīng)成功登錄,可以看到下載文件信息。
這樣,就成功模擬了HTTP客戶端的登錄。
(本文作者原創(chuàng),除非明確授權(quán)禁止轉(zhuǎn)載)
本文源碼地址:
https://gitee.com/zl3624/harmonyos_network_samples/tree/master/code/http/SimulateLogin
本系列源碼地址: