Java Http網(wǎng)絡請求HttpURLConnection應用之【Android網(wǎng)絡請求框架底層剖析】

URLConnection是個抽象類租幕,它有兩個直接子類分別是HttpURLConnection和JarURLConnection闯狱。另外一個重要的類是URL辆飘,通常URL可以通過傳給構(gòu)造器一個String類型的參數(shù)來生成一個指向特定地址的URL實例咕晋。
每個 HttpURLConnection 實例都可用于生成單個請求趁矾,但是其他實例可以透明地共享連接到 HTTP 服務器的基礎(chǔ)網(wǎng)絡。請求后在 HttpURLConnection 的 InputStream 或 OutputStream 上調(diào)用 close() 方法可以釋放與此實例關(guān)聯(lián)的網(wǎng)絡資源槽袄,但對共享的持久連接沒有任何影響。如果在調(diào)用 disconnect() 時持久連接空閑锋谐,則可能關(guān)閉基礎(chǔ)套接字遍尺。

  • 需求,發(fā)起一個Post請求涮拗,并攜帶參數(shù)給服務器乾戏,服務器返回Json數(shù)據(jù)

  • 代碼實現(xiàn)


import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;

/**
 * Created by yuandl on 2016-10-18.
 * HttpURLConnection測試
 */
public class URLConnectionTest {
    public static void main(String[] args) {
        String url = "http://10.58.178.72/intco/mobi/member/login";
        HashMap<String, String> params = new HashMap<>();
        params.put("username", "13468857714");
        params.put("pwd", MD5.md5("123456").toLowerCase());
        requestPost(url, params);
    }

    /**
     * Post請求
     *
     * @param httpUrl
     * @param paramsMap
     */
    private static void requestPost(String httpUrl, HashMap<String, String> paramsMap) {
        try {
            String baseUrl = httpUrl;
            //合成參數(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();
            System.out.println("Post方式請求地址httpUrl--->" + params);
            System.out.println("Post方式請求參數(shù)params--->" + params);
            // 請求的參數(shù)轉(zhuǎn)換為byte數(shù)組
            byte[] postData = params.getBytes();
            // 新建一個URL對象
            URL url = new URL(baseUrl);
            // 打開一個HttpURLConnection連接
            HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
            // 設置連接超時時間
            urlConn.setConnectTimeout(5 * 1000);
            //設置從主機讀取數(shù)據(jù)超時
            urlConn.setReadTimeout(5 * 1000);
            // Post請求必須設置允許輸出 默認false
            urlConn.setDoOutput(true);
            //設置請求允許輸入 默認是true
            urlConn.setDoInput(true);
            // Post請求不能使用緩存
            urlConn.setUseCaches(false);
            // 設置為Post請求
            urlConn.setRequestMethod("POST");
            //設置本次連接是否自動處理重定向
            urlConn.setInstanceFollowRedirects(true);
            // 配置請求Content-Type
            urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            // 開始連接
            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());
                System.out.println("Post方式請求成功迂苛,result--->" + result);
            } else {
                System.out.println("Post方式請求失敗");
            }
            // 關(guān)閉連接
            urlConn.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 將輸入流轉(zhuǎn)換成字符串
     *
     * @param is 從網(wǎng)絡獲取的輸入流
     * @return
     */
    public static String streamToString(InputStream is) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = is.read(buffer)) != -1) {
                baos.write(buffer, 0, len);
            }
            baos.close();
            is.close();
            byte[] byteArray = baos.toByteArray();
            return new String(byteArray);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
  • 打印結(jié)果

Post方式請求地址httpUrl--->pwd=e10adc3949ba59abbe56e057f20f883e&username=13468857714
Post方式請求參數(shù)params--->pwd=e10adc3949ba59abbe56e057f20f883e&username=13468857714
Post方式請求成功,result--->{"status":1,"data":{"mId":"426e743224db4ecb8313e069982a7496","mName":"*東亮","pwd":"f241426298243cb7f6f97da58749ffb386c1457d","sex":"1","mobile":"13468857714","authentication":"0","personal":"0","isMain":"1","parentId":"0","newOrold":"1","imgurl":"http://10.58.178.72/intco/upload/img/member/portrait/2016/10/9331f754fbb742d99f6e61dcee0fe61d.jpg","state":"1","rongcloud_token":"1XHoYMAzlXidThqzyftV8at+qlfSNm8M8gqvzen0AUEV4lvsXAvmBJF0GQBkh5JP1I3XDUvd60sWEglC4+KRsnv5d+pcovzErw8ekgl7y6fM3gYaOuFDcqN0iaV2F2PAOM4jDTjH9M8="},"msg":"登錄成功鼓择!"}

  • 總結(jié)
    • HttpURLConnection的connect()函數(shù)三幻,實際上只是建立了一個與服務器的tcp連接,并沒有實際發(fā)送http請求呐能。 無論是post還是get念搬,http請求實際上直到HttpURLConnection的getInputStream()這個函數(shù)里面才正式發(fā)送出去。
    • 在用POST方式發(fā)送URL請求時摆出,URL請求參數(shù)的設定順序是重中之重朗徊, 對connection對象的一切配置(那一堆set函數(shù)) 都必須要在connect()函數(shù)執(zhí)行之前完成。而對outputStream的寫操作偎漫,又必須要在inputStream的讀操作之前爷恳。 這些順序?qū)嶋H上是由http請求的格式?jīng)Q定的。
    • http請求實際上由兩部分組成象踊, 一個是http頭温亲,所有關(guān)于此次http請求的配置都在http頭里面定義, 一個是正文content杯矩。 connect()函數(shù)會根據(jù)HttpURLConnection對象的配置值生成http頭部信息栈虚,因此在調(diào)用connect函數(shù)之前, 就必須把所有的配置準備好菊碟。
    • 在http頭后面緊跟著的是http請求的正文节芥,正文的內(nèi)容是通過outputStream流寫入的,實際上outputStream不是一個網(wǎng)絡流逆害,充其量是個字符串流头镊,往里面寫入的東西不會立即發(fā)送到網(wǎng)絡, 而是存在于內(nèi)存緩沖區(qū)中魄幕,待outputStream流關(guān)閉時相艇,根據(jù)輸入的內(nèi)容生成http正文。 至此纯陨,http請求的東西已經(jīng)全部準備就緒坛芽。在getInputStream()函數(shù)調(diào)用的時候,就會把準備好的http請求 正式發(fā)送到服務器了翼抠,然后返回一個輸入流咙轩,用于讀取服務器對于此次http請求的返回信息。由于http 請求在getInputStream的時候已經(jīng)發(fā)送出去了(包括http頭和正文)阴颖,因此在getInputStream()函數(shù) 之后對connection對象進行設置(對http頭的信息進行修改)或者寫入outputStream(對正文進行修改) 都是沒有意義的了活喊,執(zhí)行這些操作會導致異常的發(fā)生。
  • 分析

HttpURLConnection是Java層提供的標準網(wǎng)絡請求工具類量愧,可以實現(xiàn)各種功能钾菊。通過以上的代碼和返回的請求結(jié)果可以知道帅矗,我們知道其實在Android中無論什么網(wǎng)絡請求框架,最底層也是這樣去實現(xiàn)的煞烫。我們可以在這個上面繼續(xù)封裝浑此,不斷完善就可以成為一個輕量級的Android網(wǎng)絡請求框架。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末滞详,一起剝皮案震驚了整個濱河市凛俱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茵宪,老刑警劉巖最冰,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稀火,居然都是意外死亡暖哨,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門凰狞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篇裁,“玉大人,你說我怎么就攤上這事赡若〈锊迹” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵逾冬,是天一觀的道長黍聂。 經(jīng)常有香客問我,道長身腻,這世上最難降的妖魔是什么产还? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮嘀趟,結(jié)果婚禮上脐区,老公的妹妹穿的比我還像新娘。我一直安慰自己她按,他們只是感情好牛隅,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酌泰,像睡著了一般媒佣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陵刹,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天丈攒,我揣著相機與錄音,去河邊找鬼授霸。 笑死巡验,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的碘耳。 我是一名探鬼主播显设,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辛辨!你這毒婦竟也來了捕捂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斗搞,失蹤者是張志新(化名)和其女友劉穎指攒,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體僻焚,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡允悦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了虑啤。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隙弛。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狞山,靈堂內(nèi)的尸體忽然破棺而出全闷,到底是詐尸還是另有隱情,我是刑警寧澤萍启,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布总珠,位于F島的核電站,受9級特大地震影響勘纯,放射性物質(zhì)發(fā)生泄漏局服。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一屡律、第九天 我趴在偏房一處隱蔽的房頂上張望腌逢。 院中可真熱鬧,春花似錦超埋、人聲如沸搏讶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽媒惕。三九已至,卻和暖如春来庭,著一層夾襖步出監(jiān)牢的瞬間妒蔚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肴盏,地道東北人输虱。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像洼专,于是被迫代替她去往敵國和親镇草。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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