李群


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