HttpURLConnection
HTTP的URLConnection(RFC 2616)用于通過(guò)Web發(fā)送和接收數(shù)據(jù)眯杏。數(shù)據(jù)可以是任何類型和長(zhǎng)度。該類可用于發(fā)送和接收長(zhǎng)度未預(yù)先知道的流數(shù)據(jù)捞稿。
使用步驟
HttpURLConnection使用步驟:
- 通過(guò)調(diào)用URL.openConnection()獲取新的HttpURLConnection并將結(jié)果轉(zhuǎn)換為HttpURLConnection。
- 準(zhǔn)備請(qǐng)求
請(qǐng)求的主要屬性是其URI钝尸。請(qǐng)求標(biāo)頭還可以包括諸如證書括享,content types和session cookies。 - 可選地上傳請(qǐng)求正文珍促。如果它們包含請(qǐng)求體,必須使用setDoOutput(true)來(lái)配置實(shí)例铃辖。通過(guò)寫入getOutputStream()返回的流來(lái)發(fā)送數(shù)據(jù)。
- 讀響應(yīng)猪叙。
響應(yīng)頭通常包括元數(shù)據(jù)娇斩,如響應(yīng)主體的內(nèi)容類型和長(zhǎng)度,修改的日期和會(huì)話cookie穴翩。響應(yīng)主體可以從getInputStream()返回的流中讀取犬第。如果響應(yīng)沒(méi)有body,那么該方法返回一個(gè)空的流芒帕。 - 斷開(kāi)歉嗓。
一旦響應(yīng)正文被讀取,HttpURLConnection應(yīng)該通過(guò)調(diào)用disconnect()關(guān)閉背蟆。斷開(kāi)連接釋放連接所持有的資源鉴分,以使其可能被關(guān)閉或重新使用。
Get請(qǐng)求
public static String getTask(String path){
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET"); //設(shè)置請(qǐng)求方式
conn.setConnectTimeout(5*1000); //設(shè)置連接超時(shí)時(shí)間
conn.setRequestProperty("Connection", "Keep-Alive");
InputStream in = conn.getInputStream();
//BufferedInputStream帶有緩沖區(qū)的輸入流
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[]array = new byte[1024];
int len =0;
//讀取數(shù)據(jù)
while((len = bis.read(array)) != -1){
bos.write(array, 0, len);
}
bis.close();
bos.close();
conn.disconnect(); //斷開(kāi)連接
String result = bos.toString("utf-8");
Log.i(TAG, result);
return result;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
打印
08-25 00:12:27.254: I/MainActivity(1140): <!DOCTYPE html>
08-25 00:12:27.254: I/MainActivity(1140): <html>
08-25 00:12:27.254: I/MainActivity(1140): <!--STATUS OK-->
08-25 00:12:27.254: I/MainActivity(1140): <head>
08-25 00:12:27.254: I/MainActivity(1140): <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
08-25 00:12:27.254: I/MainActivity(1140): <title>百度一下,你就知道</title>
08-25 00:12:27.254: I/MainActivity(1140): <meta http-equiv="Cache-control" content="no-cache">
//.....
setRequestMethod函數(shù)參數(shù)為String類型,必須為以下幾種:OPTIONS、GET释液、HEAD、POST坏瘩、PUT、DELETE恭应、TRACE沧烈,必須是大寫敛纲。
HttpURLConnection默認(rèn)情況下使用GET請(qǐng)求喂击。如果setDoOutput(true)已經(jīng)被調(diào)用,它將使用POST载慈。其他HTTP方法(OPTIONS惭等,HEAD珍手,PUT办铡,DELETE和TRACE)可以使用setRequestMethod(String)設(shè)置。
Post請(qǐng)求
代碼如下:
public static String postTask(String path,String post){
URL url = null;
try {
url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST"); // 提交模式
conn.setConnectTimeout(10000);//連接超時(shí) 單位毫秒
conn.setReadTimeout(2000);//讀取超時(shí) 單位毫秒
conn.setDoOutput(true); // 發(fā)送POST請(qǐng)求必須設(shè)置為true
conn.setDoInput(true); //默認(rèn)為true琳要。
conn.setFixedLengthStreamingMode(post.length());
// 獲取URLConnection對(duì)象對(duì)應(yīng)的輸出流
PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
// 發(fā)送請(qǐng)求參數(shù)
printWriter.write(post); //post的參數(shù) x=x&y=y
// flush輸出流的緩沖
printWriter.flush();
//開(kāi)始獲取數(shù)據(jù)
BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int len;
byte[] arr = new byte[1024];
while((len=bis.read(arr))!= -1){
bos.write(arr,0,len);
bos.flush();
}
bis.close();
bos.close();
conn.disconnect(); //斷開(kāi)連接
Log.i(TAG, bos.toString("utf-8"));
return bos.toString("utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
打印如下:
08-25 02:25:55.144: I/MainActivity(1205): {"success":"登錄成功"}
要將數(shù)據(jù)上傳到Web服務(wù)器寡具、使用Post請(qǐng)求,請(qǐng)使用配置連接進(jìn)行輸出 setDoOutput(true)稚补。
為了獲得最佳性能童叠,應(yīng)該setFixedLengthStreamingMode(int)提前知道身體長(zhǎng)度,或者setChunkedStreamingMode(int)不知道身長(zhǎng)课幕。否則HttpURLConnection將被強(qiáng)制緩沖內(nèi)存中的完整請(qǐng)求體厦坛,然后再傳輸,浪費(fèi)(可能耗盡)堆并增加延遲乍惊。
當(dāng)body長(zhǎng)度已事先知道時(shí)杜秸,應(yīng)該調(diào)用setFixedLengthStreamingMode(int),或者不知道長(zhǎng)度時(shí)調(diào)用setChunkedStreamingMode(int)润绎。 否則HttpURLConnection將被強(qiáng)制緩存內(nèi)存中的完整請(qǐng)求體撬碟,然后再傳輸,浪費(fèi)(可能耗盡)堆并增加延遲莉撇。
性能
HttpURLConnection呢蛤,此類返回的輸入和輸出流不會(huì)緩沖。大多數(shù)調(diào)用者都應(yīng)該使用BufferedInputStream或BufferedOutputStream來(lái)包裝返回的流棍郎。僅進(jìn)行批量讀取或?qū)懭氲恼{(diào)用者可以省略緩沖其障。
當(dāng)向服務(wù)器傳送大量數(shù)據(jù)或從服務(wù)器傳輸大量數(shù)據(jù)時(shí),請(qǐng)使用流來(lái)限制內(nèi)存中的數(shù)據(jù)量涂佃。除非您需要將整個(gè)數(shù)據(jù)一次存入內(nèi)存励翼,否則將其作為流處理(而不是將完整的數(shù)據(jù)存儲(chǔ)為單字節(jié)數(shù)組或字符串)。
為了減少延遲巡李,該類可以為多個(gè)請(qǐng)求/響應(yīng)對(duì)重用相同的底層Socket抚笔。 因此,HTTP連接可能會(huì)持續(xù)時(shí)間超過(guò)必要時(shí)間侨拦。 對(duì)disconnect()的調(diào)用可能會(huì)將套接字返回到連接的套接字池殊橙。 可以通過(guò)在發(fā)出任何HTTP請(qǐng)求之前將http.keepAlive系統(tǒng)屬性設(shè)置為false來(lái)禁用此行為。 http.maxConnections屬性可用于控制每個(gè)服務(wù)器將持有多少空閑連接。
默認(rèn)情況下膨蛮,HttpURLConnection請(qǐng)求服務(wù)器使用gzip壓縮叠纹。由于getContentLength()返回傳輸?shù)淖止?jié)數(shù),因此您無(wú)法使用該方法預(yù)測(cè)從getInputStream()可以讀取多少字節(jié)敞葛。而是讀取該流誉察,直到它:read()返回-1∪切常可以通過(guò)在請(qǐng)求標(biāo)頭中設(shè)置可接受的編碼來(lái)禁用Gzip壓縮:
urlConnection.setRequestProperty("Accept-Encoding", "identity");
網(wǎng)絡(luò)登錄
一些Wi-Fi網(wǎng)絡(luò)阻止Internet訪問(wèn)持偏,直到用戶點(diǎn)擊登錄頁(yè)面。 這種登錄頁(yè)面通常使用HTTP重定向來(lái)呈現(xiàn)氨肌。 您可以使用getURL()來(lái)測(cè)試您的連接是否意外重定向鸿秆。 此檢查無(wú)效,直到收到響應(yīng)標(biāo)頭怎囚,您可以通過(guò)調(diào)用getHeaderFields()或getInputStream()觸發(fā)卿叽。 例如,要檢查響應(yīng)是否未重定向到意外的主機(jī):
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
if (!url.getHost().equals(urlConnection.getURL().getHost())) {
// we were redirected! Kick the user out to the browser to sign on?
...
} finally {
urlConnection.disconnect();
}
}
歡迎大家關(guān)注恳守、評(píng)論考婴、點(diǎn)贊。
你們的支持是我堅(jiān)持的動(dòng)力催烘。