HttpClient和HttpURLConnection的區別


總結了網上的一些資源,主要有以下兩個觀點:

分析一:

 在研究Volley框架的源碼中,發現它在HTTP請求的使用上比較有意思,在Android 2.3及以上版本,使用的是HttpURLConnection,而在Android 2.2及以下版本,使用的是HttpClient。我也比較好奇這么使用的原因,於是專門找到了一位Google的工程師寫的一篇博客,文中對HttpURLConnection和HttpClient進行了對比,下面我就給大家簡要地翻譯一下。

原文地址:http://android-developers.blogspot.com/2011/09/androids-http-clients.html
大多數的Android應用程序都會使用HTTP協議來發送和接收網絡數據,而Android中主要提供了兩種方式來進行HTTP操作,HttpURLConnection和HttpClient。這兩種方式都支持HTTPS協議、以流的形式進行上傳和下載、配置超時時間、IPv6、以及連接池等功能。

HttpClient:

DefaultHttpClient和它的兄弟AndroidHttpClient都是HttpClient具體的實現類,它們都擁有眾多的API,而且實現比較穩定,bug數量也很少。

但同時也由於HttpClient的API數量過多,使得我們很難在不破壞兼容性的情況下對它進行升級和擴展,所以目前Android團隊在提升和優化HttpClient方面的工作態度並不積極。
HttpURLConnection:

HttpURLConnection是一種多用途、輕量極的HTTP客戶端,使用它來進行HTTP操作可以適用於大多數的應用程序。雖然HttpURLConnection的API提供的比較簡單,但是同時這也使得我們可以更加容易地去使用和擴展它。

不過在Android 2.2版本之前,HttpURLConnection一直存在着一些令人厭煩的bug。比如說對一個可讀的InputStream調用close()方法時,就有可能會導致連接池失效了。那么我們通常的解決辦法就是直接禁用掉連接池的功能:
<li class="alt"><span><span>[java]&nbsp;view&nbsp;plaincopy&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;disableConnectionReuseIfNecessary()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;這是一個2.2版本之前的bug&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(Integer.parseInt(Build.VERSION.SDK)&nbsp;<&nbsp;Build.VERSION_CODES.FROYO)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.setProperty(<span class="string">"http.keepAlive"</span><span>,&nbsp;</span><span class="string">"false"</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class=""><span>}&nbsp;&nbsp;&nbsp;&nbsp;</span></li>

配置你的Web服務器來支持對客戶端的響應進行壓縮的功能,從而可以在這一改進上獲取到最大的好處。如果在壓縮響應的時候出現了問題,這篇文檔會告訴你如何禁用掉這個功能。
但是如果啟動了響應壓縮的功能,HTTP響應頭里的Content-Length就會代表着壓縮后的長度,這時再使用getContentLength()方法來取出解壓后的數據就是錯誤的了。正確的做法應該是一直調用InputStream.read()方法來讀取響應數據,一直到出現-1為止。
我們在Android 2.3版本中還增加了一些HTTPS方面的改進,現在HttpsURLConnection會使用SNI(Server Name Indication)的方式進行連接,使得多個HTTPS主機可以共享同一個IP地址。除此之外,還增加了一些壓縮和會話的機制。如果連接失敗,它會自動去嘗試重新進行連接。這使得HttpsURLConnection可以在不破壞老版本兼容性的前提下,更加高效地連接最新的服務器。
在Android 4.0版本中,我們又添加了一些響應的緩存機制。當緩存被安裝后(調用HttpResponseCache的install()方法),所有的HTTP請求都會滿足以下三種情況:
所有的緩存響應都由本地存儲來提供。因為沒有必要去發起任務的網絡連接請求,所有的響應都可以立刻獲取到。
視情況而定的緩存響應必須要有服務器來進行更新檢查。比如說客戶端發起了一條類似於 “如果/foo.png這張圖片發生了改變,就將它發送給我” 這樣的請求,服務器需要將更新后的數據進行返回,或者返回一個304 Not Modified狀態。如果請求的內容沒有發生,客戶端就不會下載任何數據。
沒有緩存的響應都是由服務器直接提供的。這部分響應會在稍后存儲到響應緩存中。
由於這個功能是在4.0之后的版本才有的,通常我們就可以使用反射的方式來啟動響應緩存功能。下面的示例代碼展示了如何在Android 4.0及以后的版本中去啟用響應緩存的功能,同時還不會影響到之前的版本:

<li class="alt"><span><span>[java]&nbsp;view&nbsp;plaincopy&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;</span></li><li class="alt"><span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;enableHttpResponseCache()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">try</span><span>&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">long</span><span>&nbsp;httpCacheSize&nbsp;=&nbsp;</span><span class="number">10</span><span>&nbsp;*&nbsp;</span><span class="number">1024</span><span>&nbsp;*&nbsp;</span><span class="number">1024</span><span>;&nbsp;</span><span class="comment">//&nbsp;10&nbsp;MiB&nbsp;&nbsp;</span><span>&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;httpCacheDir&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;File(getCacheDir(),&nbsp;</span><span class="string">"http"</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class.forName(<span class="string">"android.net.http.HttpResponseCache"</span><span>)&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getMethod(<span class="string">"install"</span><span>,&nbsp;File.</span><span class="keyword">class</span><span>,&nbsp;</span><span class="keyword">long</span><span>.</span><span class="keyword">class</span><span>)&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.invoke(<span class="keyword">null</span><span>,&nbsp;httpCacheDir,&nbsp;httpCacheSize);&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span class="keyword">catch</span><span>&nbsp;(Exception&nbsp;httpResponseCacheNotAvailable)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class=""><span>}&nbsp;&nbsp;&nbsp;&nbsp;</span></li>

你也應該同時配置一下你的Web服務器,在HTTP響應上加入緩存的消息頭。哪一種才是最好的?在Android 2.2版本之前,HttpClient擁有較少的bug,因此使用它是最好的選擇。
而在Android 2.3版本及以后,HttpURLConnection則是最佳的選擇。它的API簡單,體積較小,因而非常適用於Android項目。壓縮和緩存機制可以有效地減少網絡訪問的流量,在提升速度和省電方面也起到了較大的作用。對於新的應用程序應該更加偏向於使用HttpURLConnection,因為在以后的工作當中我們也會將更多的時間放在優化HttpURLConnection上面。

分析二:

HTTP 協議可能是現在 Internet 上使用得最多、最重要的協議了,越來越多的 Java 應用程序需要直接通過 HTTP 協議來訪問網絡資源。在 JDK 的 java.net 包中已經提供了訪問 HTTP 協議的基本功能:HttpURLConnection。

HttpURLConnection是java的標准類,HttpURLConnection繼承自URLConnection,可用於向指定網站發送GET請求、POST請求。它在URLConnection的基礎上提供了如下便捷的方法:

int getResponseCode():獲取服務器的響應代碼。
String getResponseMessage():獲取服務器的響應消息。
String getResponseMethod():獲取發送請求的方法。
void setRequestMethod(String method):設置發送請求的方法。
在一般情況下,如果只是需要Web站點的某個簡單頁面提交請求並獲取服務器響應,HttpURLConnection完全可以勝任。但在絕大部分情況下,Web站點的網頁可能沒這么簡單,這些頁面並不是通過一個簡單的URL就可訪問的,可能需要用戶登錄而且具有相應的權限才可訪問該頁面。在這種情況下,就需要涉及Session、Cookie的處理了,如果打算使用HttpURLConnection來處理這些細節,當然也是可能實現的,只是處理起來難度就大了。
為了更好地處理向Web站點請求,包括處理Session、Cookie等細節問題,Apache開源組織提供了一個HttpClient項目,看它的名稱就知道,它是一個簡單的HTTP客戶端(並不是瀏覽器),可以用於發送HTTP請求,接收HTTP響應。但不會緩存服務器的響應,不能執行HTML頁面中嵌入的Javascript代碼;也不會對頁面內容進行任何解析、處理。
簡單來說,HttpClient就是一個增強版的HttpURLConnection,HttpURLConnection可以做的事情HttpClient全部可以做;HttpURLConnection沒有提供的有些功能,HttpClient也提供了,但它只是關注於如何發送請求、接收
響應,以及管理HTTP連接。
使用HttpClient發送請求、接收響應很簡單,只要如下幾步即可。

創建HttpClient對象。
如果需要發送GET請求,創建HttpGet對象;如果需要發送POST請求,創建HttpPost對象。
如果需要發送請求參數,可調用HttpGet、HttpPost共同的setParams(HetpParams params)方法來添加請求參數;對於HttpPost對象而言,也可調用setEntity(HttpEntity entity)方法來設置請求參數。
調用HttpClient對象的execute(HttpUriRequest request)發送請求,執行該方法返回一個HttpResponse。
調用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可獲取服務器的響應頭;調用HttpResponse的getEntity()方法可獲取HttpEntity對象,該對象包裝了服務器的響應內容。程序可通過該對象獲取服務器的響應內容。
另外,Android已經成功地集成了HttpClient,這意味着開發人員可以直接在Android應用中使用Httpclient來訪問提交請求、接收響應。
比如一個Android應用需要向指定頁面發送請求,但該頁面並不是一個簡單的頁面,只有當用戶已經登錄,而且登錄用戶的用戶名有效時才可訪問該頁面。如果使用HttpURLConnection來訪問這個被保護的頁面,那么需要處理的細節就太復雜了。
其實訪問Web應用中被保護的頁面,使用瀏覽器則十分簡單,用戶通過系統提供的登錄頁面登錄系統,瀏覽器會負責維護與服務器之間的Sesion,如果用戶登錄的用戶名、密碼符合要求,就可以訪問被保護資源了。
在Android應用程序中,則可使用HttpClient來登錄系統,只要應用程序使用同一個HttpClient發送請求,HttpClient會自動維護與服務器之間的Session狀態,也就是說程序第一次使用HttpClient登錄系統后,接下來使用HttpClient即可訪問被保護頁而了。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com