李群
摘要 OkHttp是一種面向HTTP客戶端的JAVA平臺(tái)開發(fā)庫(kù),具有網(wǎng)絡(luò)訪問高效穩(wěn)定、易于開發(fā)等特性。通過對(duì)OkHttp開發(fā)庫(kù)的分析,提出了基于OkHt tp的文件傳輸接口的設(shè)計(jì)方法。使用本文實(shí)現(xiàn)的接口,可以方便快捷地完成各類文件傳輸?shù)男枨蟆?/p>
【關(guān)鍵詞】文件傳輸 面向?qū)ο?HTTP
1 引言
伴隨著各行業(yè)管理網(wǎng)絡(luò)化和自動(dòng)化的逐步深入,本單位對(duì)各類電子文件通過網(wǎng)絡(luò)進(jìn)行傳輸?shù)男枨笕找嬖鰪?qiáng)。在本單位現(xiàn)有局域網(wǎng)帶寬有限的情況下,高效穩(wěn)定傳輸文件是急需解決的一項(xiàng)工作。
文件傳輸(File transfer)指將一個(gè)文件或其中一部分通過網(wǎng)絡(luò)從一個(gè)計(jì)算機(jī)系統(tǒng)傳到另一個(gè)計(jì)算機(jī)系統(tǒng),用于存儲(chǔ)、遠(yuǎn)程訪問、運(yùn)行或者打印等各項(xiàng)處理任務(wù)。由于網(wǎng)絡(luò)中各個(gè)計(jì)算機(jī)的文件系統(tǒng)往往并不相同,因此,通常要采用某一網(wǎng)絡(luò)應(yīng)用層協(xié)議作為公用的文件傳輸規(guī)則。目前,常用的文件傳輸協(xié)議主要包括文件傳輸協(xié)議(FTP)和超文本傳輸協(xié)議(HTTP)。相較而言,HTTP更適合同時(shí)傳輸多個(gè)文件等應(yīng)用場(chǎng)景,是本文所采用的文件傳輸協(xié)議。各大公司針對(duì)HTTP協(xié)議提供了多種開發(fā)庫(kù),例如面向C/C++的Boost.Asio、面向Python的Twisted等。本文介紹的工作基于面向Java的OkHttp,確保所開發(fā)的文件傳輸模塊具有跨平臺(tái)能力。
2 0kHttp
2.1 0kHttp簡(jiǎn)介
OkHttp是由Square公司提供的一種面向HTTP客戶端的開發(fā)庫(kù)。OkHttp處理HTTP協(xié)議的特點(diǎn)如下:
(1)支持HTTP/2和SPDY,允許同一主機(jī)共享一個(gè)套接字的所有請(qǐng)求;
(2)當(dāng)SPDY不可用,連接池可降低請(qǐng)求延遲;
(3)透明GZIP可降低下載量;
(4)響應(yīng)緩存可避免重復(fù)的請(qǐng)求;
(5)同時(shí)支持同步阻塞調(diào)用和基于回調(diào)的異步調(diào)用。通過使用OkHttp,開發(fā)者在實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用時(shí)可大大減少所需的步驟。開發(fā)者無需關(guān)注網(wǎng)絡(luò)測(cè)試、從常見連接問題中恢復(fù);在連接失敗時(shí),OkHttp可以嘗試不同的路由重新請(qǐng)求。OkHttp通過創(chuàng)建共享內(nèi)存池,提高讀寫數(shù)據(jù)的速度。此外,作為Retrofit庫(kù)的底層庫(kù),OkHttp為使用基于REST的API提供了類型安全性。若需使用OkHttp,Java的最低版本要求為1.7。
2.2 0kHttp核心類
使用OkHttp開發(fā)庫(kù),首先必須了解該庫(kù)所提供的核心類。
(1) OkHttpClient類對(duì)HTTP客戶端進(jìn)行管理,接受請(qǐng)求(request)并產(chǎn)生對(duì)應(yīng)的響應(yīng)(response)。所有的HTTP客戶端都在OkHttpClient中配置,包括代理設(shè)置、超時(shí)和緩存等。在使用OkHttp時(shí),應(yīng)盡量建立單個(gè)OkHttpClient實(shí)例用于HTTP調(diào)用,以獲得最佳性能。其原因在于,每個(gè)客戶端維護(hù)自己的連接池和線程池,連接和線程的重用可降低延遲并節(jié)省內(nèi)存。如果為每個(gè)請(qǐng)求創(chuàng)建一個(gè)客戶端,會(huì)導(dǎo)致空閑池上的資源浪費(fèi)。
(2) Request類表示HTTP請(qǐng)求。該類采用生成式設(shè)計(jì)模式構(gòu)建實(shí)例,用來設(shè)置復(fù)雜參數(shù),示例如下:
Request request= new Request.Builder()url(”http://www.baidu.com”).build();
(3)Response類表示HTTP響應(yīng)。通過isSuccessful()方法判斷請(qǐng)求是否成功。對(duì)于成功的響應(yīng),可以通過body()以及header()方法獲取HTTP響應(yīng)的內(nèi)容。
(4) Call類是表示已經(jīng)準(zhǔn)備完畢等待執(zhí)行的請(qǐng)求。Call請(qǐng)求可以被取消。此外,由于Call對(duì)象表示單個(gè)請(qǐng)求/響應(yīng)對(duì),因此無法被執(zhí)行兩次。
3 文件傳輸設(shè)計(jì)
根據(jù)上節(jié)所介紹的OkHttp使用方法,結(jié)合日常文件傳輸?shù)男枨螅疚脑O(shè)計(jì)了一套基于OkHttp的文件傳輸接口,便于二次開發(fā)。
3.1 HTTP請(qǐng)求過程
使用OkHttp進(jìn)行網(wǎng)絡(luò)請(qǐng)求的步驟歸納為以下四點(diǎn):
(1)創(chuàng)建一個(gè)OkHttpClient實(shí)例;
(2)創(chuàng)建一個(gè)Request實(shí)例;
(3)使用OkHttpClient創(chuàng)建一個(gè)Call并執(zhí)行,獲取一個(gè)Response對(duì)象;
(4)對(duì)Response進(jìn)行相關(guān)操作。通過以上四個(gè)步驟,一個(gè)應(yīng)用可以完成各種情況下的網(wǎng)絡(luò)訪問。
其中,在步驟3的執(zhí)行過程中,可以根據(jù)同步或者異步需求,分別采用execute()方法或者enqueue()方法,實(shí)現(xiàn)不同的訪問策略。在步驟2創(chuàng)建Request實(shí)例時(shí),用戶可以根據(jù)需要發(fā)起Post請(qǐng)求或者Get請(qǐng)求。Post或者Get是HTTP協(xié)議中向后臺(tái)服務(wù)器發(fā)送數(shù)據(jù)的一種機(jī)制,是HTTP協(xié)議的一個(gè)組成部分。Post請(qǐng)求將要提交到后臺(tái)服務(wù)器的數(shù)據(jù)放在HTTP包的包體中,Get請(qǐng)求將數(shù)據(jù)放在URL之后。相較而言,Post請(qǐng)求方式更加安全,而Get請(qǐng)求方式更加便捷。
3.2 文件傳輸類設(shè)計(jì)
由于基于OkHttp文件傳輸過程既具有統(tǒng)一性又具有差異性,本文在設(shè)計(jì)類時(shí),采用了抽象類(Abstract class)及其派生子類的方法。抽象類用于創(chuàng)建體現(xiàn)某些基本行為的類,并為該類聲明方法但不能在該類中實(shí)現(xiàn)。通過抽象類,描述基于OkHttp文件傳輸?shù)幕静襟E,體現(xiàn)傳輸行為的統(tǒng)一性。通過抽象類派生的子類,實(shí)現(xiàn)同步傳輸或者異步傳輸,體現(xiàn)傳輸行為的差異性。本文設(shè)計(jì)的文件傳輸類繼承結(jié)構(gòu)如圖1所示。
每個(gè)類的具體說明如下:
(1) OkHttpTransfer類為抽象父類,負(fù)責(zé)定義文件傳輸相關(guān)的方法。該類擁有一個(gè)HTTP客戶端實(shí)例,定義為protected finalOkHttpClient client,通過該實(shí)例管理所有HTTP的傳輸。該類的核心方法如表l所示。
OkHttpTransfer類對(duì)傳輸過程進(jìn)行了實(shí)現(xiàn)。其中runDownlaod的實(shí)現(xiàn)核心代碼為:
Thread myThread= new Thread(newRunnable(){
public void run(){
Request request= new Request.Builder().url(targetUrl).build();
callWith(request);
)
});
myThread.start();
runUpload方法與runDownlaod方法類似;不同之處是由于文件較大,采用post方法生成Request。
(2) SynchronousTransfer類, 派生自O(shè)kHttpTransfer類,實(shí)現(xiàn)了同步傳輸?shù)腃all執(zhí)行。在該類里,具體實(shí)現(xiàn)了caIIWith方法,調(diào)用了Call類的execute方法,關(guān)鍵代碼如下:
try{
Response response= client.newCall(request).execute();
if (fresponse.isSuccessful(》
throw newIOException(”Unexpected code”+response);
analyzeResponse(response);
} catch (Exception e)
(3) AsynchronousTransfer類在實(shí)現(xiàn)callWith方法時(shí),則調(diào)用了Call類的enqueue方法,關(guān)鍵代碼如下:
client.newCall(request).enqueue(newCallback(){
public void onFailure(Call call,IOException e)……
public void onResponse(Call call,Response response) throws IOException{
try{
if (!response.isSuccessful(》
throw newIOException(”Unexpected code”+response);
analyzeResponse(response);
} catch (Exception e)
}
));
在使用時(shí),用戶根據(jù)需求生成SynchronousTransfer或者AsynchronousTransfer實(shí)例,調(diào)用runDownlaod方法或者runUpload方法,實(shí)現(xiàn)不同的文件傳輸策略,接口簡(jiǎn)潔易用。
4 結(jié)語(yǔ)
本文介紹了一種基于OkHttp客戶端的文件傳輸接口設(shè)計(jì)與實(shí)現(xiàn)。OkHttp開發(fā)庫(kù)具有網(wǎng)絡(luò)訪問高效穩(wěn)定、易于開發(fā)等特性。本文針對(duì)文件傳輸?shù)男枨?,?duì)OkHttp開發(fā)庫(kù)提供的類和方法進(jìn)行了封裝,使得文件傳輸過程可被復(fù)用,接口調(diào)用簡(jiǎn)潔。
參考文獻(xiàn)
[1] Bruce Eckel.Java編程思想[M],北京:機(jī)械工業(yè)出版社,2007.
[2] Elliotte Rusty Harold。Java網(wǎng)絡(luò)編程[M].北京:中國(guó)電力出版社,2014.
[3][ al上野·宣,圖解HTTP [M].北京:人民郵電出版社,2014.