Android-淺析-HttpURLConnection

原文:https://jasonzhong.github.io/2017/01/26/Android-%E6%B5%85%E6%9E%90-HttpURLConnection/

前言

Linus Benedict Torvalds : RTFSC – Read The Funning Source Code

概述

HttpURLConnection是一種多用途、輕量極的HTTP客戶端,使用它來進(jìn)行HTTP操作可以適用于大多數(shù)的應(yīng)用程序傅瞻。

HttpURLConnection相對于HttpClient的優(yōu)點(diǎn):

HttpURLConnection HttpClient
Android SDK的標(biāo)準(zhǔn)實(shí)現(xiàn) apache的開源實(shí)現(xiàn)
支持GZIP壓縮 也支持GZIP壓縮触创,但處理
支持系統(tǒng)級連接池,即打開的連接不會直接關(guān)閉,在一段時間內(nèi)所有程序可共用 不如官方直接系統(tǒng)底層支持好
在系統(tǒng)層面做了緩存策略處理,加快重復(fù)請求的速度

使用

使用這個類應(yīng)該跟從以下步驟:

Step 1

Obtain a new HttpURLConnection by calling URL.openConnection() and casting the result to HttpURLConnection. 獲得一個新的HttpURLConnection類應(yīng)該調(diào)用URL.openConnection()并且將結(jié)果強(qiáng)轉(zhuǎn)成HttpURLConnection類照藻。

Step 2

Prepare the request. The primary property of a request is its URI. Request headers may also include metadata such as credentials, preferred content types, and session cookies.準(zhǔn)備一個request免钻。這個request主要屬性是它的URI彼水。Request的頭部將會包含一些元數(shù)據(jù)例如憑證,首選內(nèi)容類型和會話Cookie极舔。

Step 3

Optionally upload a request body. Instances must be configured with setDoOutput(true) if they include a request body. Transmit data by writing to the stream returned by getOutputStream().可選上傳的request內(nèi)容凤覆。如果它包含一個request內(nèi)容,實(shí)例必須配置為setDoOutput(true)拆魏。通過寫入getOutputStream()返回的流來傳輸數(shù)據(jù)盯桦。

Step 4

Read the response. Response headers typically include metadata such as the response body's content type and length, modified dates and session cookies. The response body may be read from the stream returned by getInputStream(). If the response has no body, that method returns an empty stream.讀取響應(yīng)。響應(yīng)標(biāo)頭通常包括元數(shù)據(jù)稽揭,例如響應(yīng)正文的內(nèi)容類型和長度,修改日期和會話Cookie肥卡。 響應(yīng)主體可以從getInputStream()返回的流中讀取溪掀。 如果響應(yīng)沒有正文,那么該方法將返回一個空流步鉴。

Step 5

Disconnect. Once the response body has been read, the HttpURLConnection should be closed by calling disconnect(). Disconnecting releases the resources held by a connection so they may be closed or reused.斷開鏈接揪胃。一旦響應(yīng)內(nèi)容被讀取,HttpURLConnection應(yīng)該要被關(guān)閉用disconnect()函數(shù)氛琢。斷開連接釋放連接持有的資源喊递,以便它們可以被關(guān)閉或重用。

例子

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
  InputStream in = new BufferedInputStream(urlConnection.getInputStream());
  readStream(in);
} finally {
  urlConnection.disconnect();
}

返回值

類型 鍵值
HTTP_ACCEPTED HTTP Status-Code 202: Accepted.
HTTP_BAD_GATEWAY HTTP Status-Code 502: Bad Gateway.
HTTP_BAD_METHOD HTTP Status-Code 405: Method Not Allowed.
HTTP_BAD_REQUEST HTTP Status-Code 400: Bad Request.
HTTP_CLIENT_TIMEOUT HTTP Status-Code 408: Request Time-Out.
HTTP_CONFLICT HTTP Status-Code 409: Conflict.
HTTP_CREATED HTTP Status-Code 201: Created.
HTTP_ENTITY_TOO_LARGE HTTP Status-Code 413: Request Entity Too Large.
HTTP_FORBIDDEN HTTP Status-Code 403: Forbidden.
HTTP_GATEWAY_TIMEOUT HTTP Status-Code 504: Gateway Timeout.
HTTP_GONE HTTP Status-Code 410: Gone.
HTTP_INTERNAL_ERROR HTTP Status-Code 500: Internal Server Error.
HTTP_LENGTH_REQUIRED HTTP Status-Code 411: Length Required.
HTTP_MOVED_PERM HTTP Status-Code 301: Moved Permanently.
HTTP_MOVED_TEMP HTTP Status-Code 302: Temporary Redirect.
HTTP_MULT_CHOICE HTTP Status-Code 300: Multiple Choices.
HTTP_NOT_ACCEPTABLE HTTP Status-Code 406: Not Acceptable.
HTTP_NOT_AUTHORITATIVE HTTP Status-Code 203: Non-Authoritative Information.
HTTP_NOT_FOUND HTTP Status-Code 404: Not Found.
HTTP_NOT_IMPLEMENTED HTTP Status-Code 501: Not Implemented.
HTTP_NOT_MODIFIED HTTP Status-Code 304: Not Modified.
HTTP_NO_CONTENT HTTP Status-Code 204: No Content.
HTTP_OK HTTP Status-Code 200: OK.
HTTP_PARTIAL HTTP Status-Code 206: Partial Content.
HTTP_PAYMENT_REQUIRED HTTP Status-Code 402: Payment Required.
HTTP_PRECON_FAILED HTTP Status-Code 412: Precondition Failed.
HTTP_PROXY_AUTH HTTP Status-Code 407: Proxy Authentication Required.
HTTP_REQ_TOO_LONG HTTP Status-Code 414: Request-URI Too Large.
HTTP_RESET HTTP Status-Code 205: Reset Content.
HTTP_SEE_OTHER HTTP Status-Code 303: See Other.
HTTP_SERVER_ERROR This constant was deprecated in API level 1. it is misplaced and shouldn't have existed.
HTTP_UNAUTHORIZED HTTP Status-Code 401: Unauthorized.
HTTP_UNAVAILABLE HTTP Status-Code 503: Service Unavailable.
HTTP_UNSUPPORTED_TYPE HTTP Status-Code 415: Unsupported Media Type.
HTTP_USE_PROXY HTTP Status-Code 305: Use Proxy.
HTTP_VERSION HTTP Status-Code 505: HTTP Version Not Supported.

針對鏈接的屬性一些定義:


通用首部字段

請求首部字段

響應(yīng)首部字段

實(shí)體首部字段

詳細(xì)使用

Get操作

private void requestGet(HashMap<String, String> paramsMap) {
    try {
        String baseUrl = "https://baidu.com/";
        StringBuilder tempParams = new StringBuilder();
        int pos = 0;
        for (String key : paramsMap.keySet()) {
            if (pos > 0) {
                tempParams.append("&");
            }
            tempParams.append(String.format("%s=%s", key, URLEncoder.encode(paramsMap.get(key),"utf-8")));
            pos++;
        }
        String requestUrl = baseUrl + tempParams.toString();
        // 新建一個URL對象
        URL url = new URL(requestUrl);
        // 打開一個HttpURLConnection連接
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        // 設(shè)置連接主機(jī)超時時間
        urlConn.setConnectTimeout(5 * 1000);
        // 設(shè)置從主機(jī)讀取數(shù)據(jù)超時
        urlConn.setReadTimeout(5 * 1000);
        // 設(shè)置是否使用緩存  默認(rèn)是true
        urlConn.setUseCaches(true);
        // 設(shè)置為Post請求
        urlConn.setRequestMethod("GET");
        // urlConn設(shè)置請求頭信息
        // 設(shè)置請求中的媒體類型信息阳似。
        urlConn.setRequestProperty("Content-Type", "application/json");
        // 設(shè)置客戶端與服務(wù)連接類型
        urlConn.addRequestProperty("Connection", "Keep-Alive");
        // 開始連接
        urlConn.connect();
        // 判斷請求是否成功
        if (urlConn.getResponseCode() == 200) {
            // 獲取返回的數(shù)據(jù)
            String result = streamToString(urlConn.getInputStream());
            Log.e(TAG, "Get方式請求成功骚勘,result--->" + result);
        } else {
            Log.e(TAG, "Get方式請求失敗");
        }
        // 關(guān)閉連接
        urlConn.disconnect();
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }
}

Post操作

private void requestPost(HashMap<String, String> paramsMap) {
    try {
        String baseUrl = "https://baidu.com/";
        // 合成參數(shù)
        StringBuilder tempParams = new StringBuilder();
        int pos = 0;
        for (String key : paramsMap.keySet()) {
            if (pos > 0) {
                tempParams.append("&");
            }
            tempParams.append(String.format("%s=%s", key,  URLEncoder.encode(paramsMap.get(key),"utf-8")));
            pos++;
        }
        String params =tempParams.toString();
        // 請求的參數(shù)轉(zhuǎn)換為byte數(shù)組
        byte[] postData = params.getBytes();
        // 新建一個URL對象
        URL url = new URL(baseUrl);
        // 打開一個HttpURLConnection連接
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        // 設(shè)置連接超時時間
        urlConn.setConnectTimeout(5 * 1000);
        // 設(shè)置從主機(jī)讀取數(shù)據(jù)超時
        urlConn.setReadTimeout(5 * 1000);
        // Post請求必須設(shè)置允許輸出 默認(rèn)false
        urlConn.setDoOutput(true);
        // 設(shè)置請求允許輸入 默認(rèn)是true
        urlConn.setDoInput(true);
        // Post請求不能使用緩存
        urlConn.setUseCaches(false);
        // 設(shè)置為Post請求
        urlConn.setRequestMethod("POST");
        // 設(shè)置本次連接是否自動處理重定向
        urlConn.setInstanceFollowRedirects(true);
        // 配置請求Content-Type
        urlConn.setRequestProperty("Content-Type", "application/json");
        // 開始連接
        urlConn.connect();
        // 發(fā)送請求參數(shù)
        DataOutputStream dos = new DataOutputStream(urlConn.getOutputStream());
        dos.write(postData);
        dos.flush();
        dos.close();
        // 判斷請求是否成功
        if (urlConn.getResponseCode() == 200) {
            // 獲取返回的數(shù)據(jù)
            String result = streamToString(urlConn.getInputStream());
            Log.e(TAG, "Post方式請求成功,result--->" + result);
        } else {
            Log.e(TAG, "Post方式請求失敗");
        }
        // 關(guān)閉連接
        urlConn.disconnect();
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }
}

download操作

private void downloadFile(String fileUrl){
    try {
        // 新建一個URL對象
        URL url = new URL(fileUrl);
        // 打開一個HttpURLConnection連接
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        // 設(shè)置連接主機(jī)超時時間
        urlConn.setConnectTimeout(5 * 1000);
        // 設(shè)置從主機(jī)讀取數(shù)據(jù)超時
        urlConn.setReadTimeout(5 * 1000);
        // 設(shè)置是否使用緩存  默認(rèn)是true
        urlConn.setUseCaches(true);
        // 設(shè)置為Post請求
        urlConn.setRequestMethod("GET");
        // urlConn設(shè)置請求頭信息
        // 設(shè)置請求中的媒體類型信息撮奏。
        urlConn.setRequestProperty("Content-Type", "application/json");
        // 設(shè)置客戶端與服務(wù)連接類型
        urlConn.addRequestProperty("Connection", "Keep-Alive");
        // 開始連接
        urlConn.connect();
        // 判斷請求是否成功
        if (urlConn.getResponseCode() == 200) {
            String filePath="";
            File  descFile = new File(filePath);
            FileOutputStream fos = new FileOutputStream(descFile);;
            byte[] buffer = new byte[1024];
            int len;
            InputStream inputStream = urlConn.getInputStream();
            while ((len = inputStream.read(buffer)) != -1) {
                // 寫到本地
                fos.write(buffer, 0, len);
            }
        } else {
            Log.e(TAG, "文件下載失敗");
        }
        // 關(guān)閉連接
        urlConn.disconnect();
    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }
}

上傳操作

private void upLoadFile(String filePath, HashMap<String, String> paramsMap) {
    try {
        String baseUrl = "https://baidu.com/uploadFile";
        File file = new File(filePath);
        // 新建url對象
        URL url = new URL(baseUrl);
        // 通過HttpURLConnection對象,向網(wǎng)絡(luò)地址發(fā)送請求
        HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
        // 設(shè)置該連接允許讀取
        urlConn.setDoOutput(true);
        // 設(shè)置該連接允許寫入
        urlConn.setDoInput(true);
        // 設(shè)置不能適用緩存
        urlConn.setUseCaches(false);
        // 設(shè)置連接超時時間
        urlConn.setConnectTimeout(5 * 1000);   // 設(shè)置連接超時時間
        // 設(shè)置讀取超時時間
        urlConn.setReadTimeout(5 * 1000);   // 讀取超時
        // 設(shè)置連接方法post
        urlConn.setRequestMethod("POST");
        // 設(shè)置維持長連接
        urlConn.setRequestProperty("connection", "Keep-Alive");
        // 設(shè)置文件字符集
        urlConn.setRequestProperty("Accept-Charset", "UTF-8");
        // 設(shè)置文件類型
        urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + "*****");
        String name = file.getName();
        DataOutputStream requestStream = new DataOutputStream(urlConn.getOutputStream());
        requestStream.writeBytes("--" + "*****" + "\r\n");
        // 發(fā)送文件參數(shù)信息
        StringBuilder tempParams = new StringBuilder();
        tempParams.append("Content-Disposition: form-data; name=\"" + name + "\"; filename=\"" + name + "\"; ");
        int pos = 0;
        int size = paramsMap.size();
        for (String key : paramsMap.keySet()) {
            tempParams.append( String.format("%s=\"%s\"", key, paramsMap.get(key), "utf-8"));
            if (pos < size-1) {
                tempParams.append("; ");
            }
            pos++;
        }
        tempParams.append("\r\n");
        tempParams.append("Content-Type: application/octet-stream\r\n");
        tempParams.append("\r\n");
        String params = tempParams.toString();
        requestStream.writeBytes(params);
        //發(fā)送文件數(shù)據(jù)
        FileInputStream fileInput = new FileInputStream(file);
        int bytesRead;
        byte[] buffer = new byte[1024];
        DataInputStream in = new DataInputStream(new FileInputStream(file));
        while ((bytesRead = in.read(buffer)) != -1) {
            requestStream.write(buffer, 0, bytesRead);
        }
        requestStream.writeBytes("\r\n");
        requestStream.flush();
        requestStream.writeBytes("--" + "*****" + "--" + "\r\n");
        requestStream.flush();
        fileInput.close();
        int statusCode = urlConn.getResponseCode();
        if (statusCode == 200) {
            // 獲取返回的數(shù)據(jù)
            String result = streamToString(urlConn.getInputStream());
            Log.e(TAG, "上傳成功俏讹,result--->" + result);
        } else {
            Log.e(TAG, "上傳失敗");
        }
    } catch (IOException e) {
        Log.e(TAG, e.toString());
    }
}

Request部分

Header 解釋 示例
Accept 指定客戶端能夠接收的內(nèi)容類型 Accept: text/plain, text/html
Accept-Charset 瀏覽器可以接受的字符編碼集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定瀏覽器可以支持的web服務(wù)器返回內(nèi)容壓縮編碼類型畜吊。 Accept-Encoding: compress, gzip
Accept-Language 瀏覽器可接受的語言 Accept-Language: en,zh
Accept-Ranges 可以請求網(wǎng)頁實(shí)體的一個或者多個子范圍字段 Accept-Ranges: bytes
Authorization HTTP授權(quán)的授權(quán)證書 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定請求和響應(yīng)遵循的緩存機(jī)制 Cache-Control: no-cache
Connection 表示是否需要持久連接泽疆。(HTTP 1.1默認(rèn)進(jìn)行持久連接) Connection: close
Cookie HTTP請求發(fā)送時,會把保存在該請求域名下的所有cookie值一起發(fā)送給web服務(wù)器玲献。 Cookie: $Version=1; Skin=new;
Content-Length 請求的內(nèi)容長度 Content-Length: 348
Content-Type 請求的與實(shí)體對應(yīng)的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 請求發(fā)送的日期和時間 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 請求的特定的服務(wù)器行為 Expect: 100-continue
From 發(fā)出請求的用戶的Email From: user@email.com
Host 指定請求的服務(wù)器的域名和端口號 Host: www.zcmhi.com
If-Match 只有請求內(nèi)容與實(shí)體相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果請求的部分在指定時間之后被修改則請求成功殉疼,未被修改則返回304代碼 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果內(nèi)容未改變返回304代碼,參數(shù)為服務(wù)器先前發(fā)送的Etag捌年,與服務(wù)器回應(yīng)的Etag比較判斷是否改變 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果實(shí)體未改變瓢娜,服務(wù)器發(fā)送客戶端丟失的部分,否則發(fā)送整個實(shí)體礼预。參數(shù)也為Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在實(shí)體在指定時間之后未被修改才請求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通過代理和網(wǎng)關(guān)傳送的時間 Max-Forwards: 10
Pragma 用來包含實(shí)現(xiàn)特定的指令 Pragma: no-cache
Proxy-Authorization 連接到代理的授權(quán)證書 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只請求實(shí)體的一部分恋腕,指定范圍 Range: bytes=500-999
Referer 先前網(wǎng)頁的地址,當(dāng)前請求網(wǎng)頁緊隨其后,即來路 Referer: http://www.zcmhi.com/archives/71.html
TE 客戶端愿意接受的傳輸編碼逆瑞,并通知服務(wù)器接受接受尾加頭信息 TE: trailers,deflate;q=0.5
Upgrade 向服務(wù)器指定某種傳輸協(xié)議以便服務(wù)器進(jìn)行轉(zhuǎn)換(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的內(nèi)容包含發(fā)出請求的用戶信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中間網(wǎng)關(guān)或代理服務(wù)器地址荠藤,通信協(xié)議 Via: 1.0 fred, 1.1 nowhere.com

Responses 部分

Header 解釋 示例
Accept-Ranges 表明服務(wù)器是否支持指定范圍請求及哪種類型的分段請求 Accept-Ranges: bytes
Age 從原始服務(wù)器到代理緩存形成的估算時間(以秒計伙单,非負(fù)) Age: 12
Allow 對某網(wǎng)絡(luò)資源的有效的請求行為,不允許則返回405 Allow: GET, HEAD
Cache-Control 告訴所有的緩存機(jī)制是否可以緩存及哪種類型 Cache-Control: no-cache
Content-Encoding web服務(wù)器支持的返回內(nèi)容壓縮編碼類型哈肖。 Content-Encoding: gzip
Content-Language 響應(yīng)體的語言 Content-Language: en,zh
Content-Length 響應(yīng)體的長度 Content-Length: 348
Content-Location 請求資源可替代的備用的另一地址 Content-Location: /index.htm
Content-MD5 返回資源的MD5校驗(yàn)值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整個返回體中本部分的字節(jié)位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回內(nèi)容的MIME類型 Content-Type: text/html; charset=utf-8
Date 原始服務(wù)器消息發(fā)出的時間 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 請求變量的實(shí)體標(biāo)簽的當(dāng)前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 響應(yīng)過期的日期和時間 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 請求資源的最后修改時間 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用來重定向接收方到非請求URL的位置來完成請求或標(biāo)識新的資源 Location: http://www.zcmhi.com/archives/94.html
Pragma 包括實(shí)現(xiàn)特定的指令吻育,它可應(yīng)用到響應(yīng)鏈上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出認(rèn)證方案和可應(yīng)用到代理的該URL上的參數(shù) Proxy-Authenticate: Basic
refresh 應(yīng)用于重定向或一個新的資源被創(chuàng)造淤井,在5秒之后重定向(由網(wǎng)景提出布疼,被大部分瀏覽器支持) Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After 如果實(shí)體暫時不可取,通知客戶端在指定時間之后再次嘗試 Retry-After: 120
Server web服務(wù)器軟件名稱 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 設(shè)置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出頭域在分塊傳輸編碼的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件傳輸編碼 Transfer-Encoding:chunked
Vary 告訴下游代理是使用緩存響應(yīng)還是從原始服務(wù)器請求 Vary: *
Via 告知代理客戶端響應(yīng)是通過哪里發(fā)送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告實(shí)體可能存在的問題 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客戶端請求實(shí)體應(yīng)該使用的授權(quán)方案 WWW-Authenticate: Basic

注意點(diǎn)

  1. HttpURLConnection的connect()函數(shù)币狠,實(shí)際上只是建立了一個與服務(wù)器的tcp連接游两,并沒有實(shí)際發(fā)送http請求。 無論是post還是get漩绵,http請求實(shí)際上直到HttpURLConnection的getInputStream()這個函數(shù)里面才正式發(fā)送出去贱案。
  2. 在用POST方式發(fā)送URL請求時,URL請求參數(shù)的設(shè)定順序是重中之重止吐,對connection對象的一切配置(那一堆set函數(shù)) 都必須要在connect()函數(shù)執(zhí)行之前完成宝踪。而對outputStream的寫操作,又必須要在inputStream的讀操作之前碍扔。這些順序?qū)嶋H上是由http請求的格式?jīng)Q定的瘩燥。
  3. http請求實(shí)際上由兩部分組成,一個是http頭不同,所有關(guān)于此次http請求的配置都在http頭里面定義厉膀, 一個是正文content。connect()函數(shù)會根據(jù)HttpURLConnection對象的配置值生成http頭部信息二拐,因此在調(diào)用connect函數(shù)之前站蝠,就必須把所有的配置準(zhǔn)備好。
  4. 在http頭后面緊跟著的是http請求的正文卓鹿,正文的內(nèi)容是通過outputStream流寫入的菱魔,實(shí)際上outputStream不是一個網(wǎng)絡(luò)流,充其量是個字符串流吟孙,往里面寫入的東西不會立即發(fā)送到網(wǎng)絡(luò)澜倦, 而是存在于內(nèi)存緩沖區(qū)中,待outputStream流關(guān)閉時杰妓,根據(jù)輸入的內(nèi)容生成http正文藻治。至此,http請求的東西已經(jīng)全部準(zhǔn)備就緒巷挥。在getInputStream()函數(shù)調(diào)用的時候桩卵,就會把準(zhǔn)備好的http請求 正式發(fā)送到服務(wù)器了,然后返回一個輸入流,用于讀取服務(wù)器對于此次http請求的返回信息雏节。由于http 請求在getInputStream的時候已經(jīng)發(fā)送出去了(包括http頭和正文)胜嗓,因此在getInputStream()函數(shù) 之后對connection對象進(jìn)行設(shè)置(對http頭的信息進(jìn)行修改)或者寫入outputStream(對正文進(jìn)行修改)都是沒有意義的了,執(zhí)行這些操作會導(dǎo)致異常的發(fā)生钩乍。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末辞州,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子寥粹,更是在濱河造成了極大的恐慌变过,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,599評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涝涤,死亡現(xiàn)場離奇詭異媚狰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)阔拳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評論 3 385
  • 文/潘曉璐 我一進(jìn)店門崭孤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衫生,你說我怎么就攤上這事裳瘪⊥两” “怎么了罪针?”我有些...
    開封第一講書人閱讀 158,084評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長黄伊。 經(jīng)常有香客問我泪酱,道長,這世上最難降的妖魔是什么还最? 我笑而不...
    開封第一講書人閱讀 56,708評論 1 284
  • 正文 為了忘掉前任墓阀,我火速辦了婚禮,結(jié)果婚禮上拓轻,老公的妹妹穿的比我還像新娘斯撮。我一直安慰自己,他們只是感情好扶叉,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評論 6 386
  • 文/花漫 我一把揭開白布勿锅。 她就那樣靜靜地躺著,像睡著了一般枣氧。 火紅的嫁衣襯著肌膚如雪溢十。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評論 1 291
  • 那天达吞,我揣著相機(jī)與錄音张弛,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛吞鸭,可吹牛的內(nèi)容都是我干的寺董。 我是一名探鬼主播,決...
    沈念sama閱讀 39,120評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼瞒大,長吁一口氣:“原來是場噩夢啊……” “哼螃征!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起透敌,我...
    開封第一講書人閱讀 37,866評論 0 268
  • 序言:老撾萬榮一對情侶失蹤盯滚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后酗电,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體魄藕,經(jīng)...
    沈念sama閱讀 44,308評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評論 2 327
  • 正文 我和宋清朗相戀三年撵术,在試婚紗的時候發(fā)現(xiàn)自己被綠了背率。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡嫩与,死狀恐怖寝姿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情划滋,我是刑警寧澤饵筑,帶...
    沈念sama閱讀 34,461評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站处坪,受9級特大地震影響根资,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜同窘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評論 3 317
  • 文/蒙蒙 一玄帕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧想邦,春花似錦裤纹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至骂铁,卻和暖如春吹零,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拉庵。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評論 1 267
  • 我被黑心中介騙來泰國打工灿椅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 46,571評論 2 362
  • 正文 我出身青樓茫蛹,卻偏偏與公主長得像操刀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子婴洼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評論 2 350

推薦閱讀更多精彩內(nèi)容