摘要:壓縮和緩存機(jī)制可以有效地減少網(wǎng)絡(luò)訪問(wèn)的流量,在提升速度和省電方面也起到了較大的作用。打開(kāi)來(lái)分析一下,不了解和協(xié)議原理的請(qǐng)查看網(wǎng)絡(luò)編程一協(xié)議原理這篇文章。當(dāng)然這次錯(cuò)誤是正常的,百度沒(méi)理由處理我們的這次請(qǐng)求。
前言
上一篇我們了解了HTTP協(xié)議原理,這一篇我們來(lái)講講Apache的HttpClient和Java的HttpURLConnection,這兩種都是我們平常請(qǐng)求網(wǎng)絡(luò)會(huì)用到的。無(wú)論我們是自己封裝的網(wǎng)絡(luò)請(qǐng)求類還是第三方的網(wǎng)絡(luò)請(qǐng)求框架都離不開(kāi)這兩個(gè)類庫(kù)。
1.HttpClientAndroid SDK中包含了HttpClient,在Android6.0版本直接刪除了HttpClient類庫(kù),如果仍想使用則解決方法是:
如果使用的是eclipse則在libs中加入org.apache.http.legacy.jar
這個(gè)jar包在:**sdkplatformsandroid-23optional目錄中(需要下載android 6.0的SDK)
如果使用的是android studio則 在相應(yīng)的module下的build.gradle中加入:
android { useLibrary "org.apache.http.legacy" }HttpClient的GET請(qǐng)求
首先我們來(lái)用DefaultHttpClient類來(lái)實(shí)例化一個(gè)HttpClient,并配置好默認(rèn)的請(qǐng)求參數(shù):
//創(chuàng)建HttpClient private HttpClient createHttpClient() { HttpParams mDefaultHttpParams = new BasicHttpParams(); //設(shè)置連接超時(shí) HttpConnectionParams.setConnectionTimeout(mDefaultHttpParams, 15000); //設(shè)置請(qǐng)求超時(shí) HttpConnectionParams.setSoTimeout(mDefaultHttpParams, 15000); HttpConnectionParams.setTcpNoDelay(mDefaultHttpParams, true); HttpProtocolParams.setVersion(mDefaultHttpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(mDefaultHttpParams, HTTP.UTF_8); //持續(xù)握手 HttpProtocolParams.setUseExpectContinue(mDefaultHttpParams, true); HttpClient mHttpClient = new DefaultHttpClient(mDefaultHttpParams); return mHttpClient; }
接下來(lái)創(chuàng)建HttpGet和HttpClient,請(qǐng)求網(wǎng)絡(luò)并得到HttpResponse,并對(duì)HttpResponse進(jìn)行處理:
private void useHttpClientGet(String url) { HttpGet mHttpGet = new HttpGet(url); mHttpGet.addHeader("Connection", "Keep-Alive"); try { HttpClient mHttpClient = createHttpClient(); HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet); HttpEntity mHttpEntity = mHttpResponse.getEntity(); int code = mHttpResponse.getStatusLine().getStatusCode(); if (null != mHttpEntity) { InputStream mInputStream = mHttpEntity.getContent(); String respose = converStreamToString(mInputStream); Log.i("wangshu", "請(qǐng)求狀態(tài)碼:" + code + " 請(qǐng)求結(jié)果: " + respose); mInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } }
converStreamToString方法將請(qǐng)求結(jié)果轉(zhuǎn)換成String類型:
private String converStreamToString(InputStream is) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuffer sb = new StringBuffer(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line + " "); } String respose = sb.toString(); return respose; }
最后我們開(kāi)啟線程訪問(wèn)百度:
new Thread(new Runnable() { @Override public void run() { useHttpClientGet("http://www.baidu.com"); } }).start();
請(qǐng)求的返回結(jié)果,請(qǐng)求狀態(tài)碼為200,結(jié)果就是個(gè)html頁(yè),這里只截取了部分html代碼:
GET請(qǐng)求的參數(shù)暴露在URL中,這有些不大妥當(dāng),而且URL的長(zhǎng)度也有限制:長(zhǎng)度在2048字符之內(nèi),在HTTP 1.1后URL長(zhǎng)度才沒(méi)有限制。一般情況下POST可以替代GET,接下來(lái)我們來(lái)看看HttpClient的POST請(qǐng)求。
HttpClient的POST請(qǐng)求post請(qǐng)求和get類似就是需要配置要傳遞的參數(shù):
private void useHttpClientPost(String url) { HttpPost mHttpPost = new HttpPost(url); mHttpPost.addHeader("Connection", "Keep-Alive"); try { HttpClient mHttpClient = createHttpClient(); List2.HttpURLConnectionpostParams = new ArrayList<>(); //要傳遞的參數(shù) postParams.add(new BasicNameValuePair("username", "moon")); postParams.add(new BasicNameValuePair("password", "123")); mHttpPost.setEntity(new UrlEncodedFormEntity(postParams)); HttpResponse mHttpResponse = mHttpClient.execute(mHttpPost); HttpEntity mHttpEntity = mHttpResponse.getEntity(); int code = mHttpResponse.getStatusLine().getStatusCode(); if (null != mHttpEntity) { InputStream mInputStream = mHttpEntity.getContent(); String respose = converStreamToString(mInputStream); Log.i("wangshu", "請(qǐng)求狀態(tài)碼:" + code + " 請(qǐng)求結(jié)果: " + respose); mInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } }
Android 2.2版本之前,HttpURLConnection一直存在著一些令人厭煩的bug。比如說(shuō)對(duì)一個(gè)可讀的InputStream調(diào)用close()方法時(shí),就有可能會(huì)導(dǎo)致連接池失效了。那么我們通常的解決辦法就是直接禁用掉連接池的功能:
private void disableConnectionReuseIfNecessary() { // 這是一個(gè)2.2版本之前的bug if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) { System.setProperty("http.keepAlive", "false"); } }
所以在Android 2.2版本以及之前的版本使用HttpClient是較好的選擇,而在Android 2.3版本及以后,HttpURLConnection則是最佳的選擇,它的API簡(jiǎn)單,體積較小,因而非常適用于Android項(xiàng)目。壓縮和緩存機(jī)制可以有效地減少網(wǎng)絡(luò)訪問(wèn)的流量,在提升速度和省電方面也起到了較大的作用。另外在Android 6.0版本中,HttpClient庫(kù)被移除了,HttpURLConnection則是以后我們唯一的選擇。
HttpURLConnection的POST請(qǐng)求因?yàn)闀?huì)了HttpURLConnection的POST請(qǐng)求那GET請(qǐng)求也就會(huì)了,所以我這里只舉出POST的例子
首先我們創(chuàng)建一個(gè)UrlConnManager類,然后里面提供getHttpURLConnection()方法用于配置默認(rèn)的參數(shù)并返回HttpURLConnection:
public static HttpURLConnection getHttpURLConnection(String url){ HttpURLConnection mHttpURLConnection=null; try { URL mUrl=new URL(url); mHttpURLConnection=(HttpURLConnection)mUrl.openConnection(); //設(shè)置鏈接超時(shí)時(shí)間 mHttpURLConnection.setConnectTimeout(15000); //設(shè)置讀取超時(shí)時(shí)間 mHttpURLConnection.setReadTimeout(15000); //設(shè)置請(qǐng)求參數(shù) mHttpURLConnection.setRequestMethod("POST"); //添加Header mHttpURLConnection.setRequestProperty("Connection","Keep-Alive"); //接收輸入流 mHttpURLConnection.setDoInput(true); //傳遞參數(shù)時(shí)需要開(kāi)啟 mHttpURLConnection.setDoOutput(true); } catch (IOException e) { e.printStackTrace(); } return mHttpURLConnection ; }
因?yàn)槲覀円l(fā)送POST請(qǐng)求,所以在UrlConnManager類中再寫(xiě)一個(gè)postParams()方法用來(lái)組織一下請(qǐng)求參數(shù)并將請(qǐng)求參數(shù)寫(xiě)入到輸出流中:
public static void postParams(OutputStream output,ListparamsList) throws IOException{ StringBuilder mStringBuilder=new StringBuilder(); for (NameValuePair pair:paramsList){ if(!TextUtils.isEmpty(mStringBuilder)){ mStringBuilder.append("&"); } mStringBuilder.append(URLEncoder.encode(pair.getName(),"UTF-8")); mStringBuilder.append("="); mStringBuilder.append(URLEncoder.encode(pair.getValue(),"UTF-8")); } BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(output,"UTF-8")); writer.write(mStringBuilder.toString()); writer.flush(); writer.close(); }
接下來(lái)我們添加請(qǐng)求參數(shù),調(diào)用postParams()方法將請(qǐng)求的參數(shù)組織好傳給HttpURLConnection的輸出流,請(qǐng)求連接并處理返回的結(jié)果:
private void useHttpUrlConnectionPost(String url) { InputStream mInputStream = null; HttpURLConnection mHttpURLConnection = UrlConnManager.getHttpURLConnection(url); try { ListpostParams = new ArrayList<>(); //要傳遞的參數(shù) postParams.add(new BasicNameValuePair("username", "moon")); postParams.add(new BasicNameValuePair("password", "123")); UrlConnManager.postParams(mHttpURLConnection.getOutputStream(), postParams); mHttpURLConnection.connect(); mInputStream = mHttpURLConnection.getInputStream(); int code = mHttpURLConnection.getResponseCode(); String respose = converStreamToString(mInputStream); Log.i("wangshu", "請(qǐng)求狀態(tài)碼:" + code + " 請(qǐng)求結(jié)果: " + respose); mInputStream.close(); } catch (IOException e) { e.printStackTrace(); } }
最后開(kāi)啟線程請(qǐng)求網(wǎng)絡(luò):
private void useHttpUrlConnectionGetThread() { new Thread(new Runnable() { @Override public void run() { useHttpUrlConnectionPost("http://www.baidu.com"); } }).start(); }
這里我們?nèi)耘f請(qǐng)求百度,看看會(huì)發(fā)生什么?
mInputStream = mHttpURLConnection.getInputStream() 這句代碼報(bào)錯(cuò)了,找不到文件。打開(kāi)Fiddler來(lái)分析一下,不了解Fiddler和HTTP協(xié)議原理的請(qǐng)查看Android網(wǎng)絡(luò)編程(一)HTTP協(xié)議原理這篇文章。
我們的請(qǐng)求報(bào)文:
看來(lái)請(qǐng)求報(bào)文沒(méi)有問(wèn)題,再來(lái)看看響應(yīng)報(bào)文:
報(bào)504錯(cuò)誤,讀取響應(yīng)的數(shù)據(jù)報(bào)錯(cuò),對(duì)于我們這次請(qǐng)求服務(wù)端不能返回完整的響應(yīng),返回的數(shù)據(jù)為0 bytes,所以mHttpURLConnection.getInputStream() 也讀不到服務(wù)端響應(yīng)的輸入流。當(dāng)然這次錯(cuò)誤是正常的,百度沒(méi)理由處理我們的這次POST請(qǐng)求。
github源碼下載
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70562.html
摘要:如何自學(xué)知識(shí)儲(chǔ)備本知識(shí)點(diǎn)不做重點(diǎn)講解對(duì)于有基礎(chǔ)的同學(xué)推薦看編程思想,鞏固基礎(chǔ),查漏補(bǔ)全,了解并熟悉更多細(xì)節(jié)知識(shí)點(diǎn)。基礎(chǔ)學(xué)習(xí)基礎(chǔ)學(xué)習(xí)對(duì)于這些基礎(chǔ)的使用谷歌官網(wǎng)給出了很好的實(shí)例。是谷歌根據(jù)自帶的改進(jìn)的。是基于谷歌內(nèi)核的一個(gè)可以作為瀏覽器的視圖。 如何自學(xué)Android 1. Java知識(shí)儲(chǔ)備 本知識(shí)點(diǎn)不做重點(diǎn)講解: 對(duì)于有基礎(chǔ)的同學(xué)推薦看《Java編程思想》,鞏固基礎(chǔ),查漏補(bǔ)全,了解...
閱讀 1993·2021-11-24 10:45
閱讀 1850·2021-10-09 09:43
閱讀 1291·2021-09-22 15:38
閱讀 1219·2021-08-18 10:19
閱讀 2837·2019-08-30 15:55
閱讀 3057·2019-08-30 12:45
閱讀 2962·2019-08-30 11:25
閱讀 356·2019-08-29 11:30