實現(xiàn)一個簡單的網(wǎng)絡(luò)框架之連接篇

實現(xiàn)連接網(wǎng)絡(luò)并獲取數(shù)據(jù)

1. 定義一個HttpStack接口

/**
 * Created by lq on 2017/5/14.
 * 該接口定義了實現(xiàn)請求的具體方法
 */
public interface HttpStack {
    //真正實現(xiàn)網(wǎng)絡(luò)請求焚鹊,并返回數(shù)據(jù)的方法
    public Response performRequest(Request<?> request);
}

2. 使用HttpClientStack方式實現(xiàn)請求

/**
 * Created by lq on 2017/5/14.
 * api 9以下使用HttpClient執(zhí)行網(wǎng)絡(luò)請求
 */

public class HttpClientStack implements HttpStack {
    //使用HttpClient執(zhí)行網(wǎng)絡(luò)請求的https配置
    HttpClientConfig mConfig = HttpClientConfig.getConfig();

    HttpClient mHttpClient = AndroidHttpClient.newInstance(mConfig.userAgent);

    @Override
    public Response performRequest(Request<?> request) {
        try {
            HttpUriRequest httpUriRequest = createHttpRequest(request);
            //添加連接參數(shù)
            setConnectionParams(httpUriRequest);
            //添加Header
            addHeaders(httpUriRequest,request.getHeaders());
            //https配置
            configHttps(request);
            //執(zhí)行網(wǎng)絡(luò)請求码荔,并返回結(jié)果
            HttpResponse response = mHttpClient.execute(httpUriRequest);
            //構(gòu)建Response
            Response rawResponse = new Response(response.getStatusLine());
            //設(shè)置Entity
            rawResponse.setEntity(response.getEntity());
            return rawResponse;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    //如果是https請求,則使用用戶配置的SSLSocketFactory進行配置
    private void configHttps(Request<?> request){
        SSLSocketFactory sslSocketFactory = mConfig.getSslSocketFactory();
        if (request.isHttps() && sslSocketFactory != null){
            Scheme scheme = new Scheme("https", (SocketFactory) sslSocketFactory,443);
            mHttpClient.getConnectionManager().getSchemeRegistry().register(scheme);
        }
    }
    //設(shè)置連接參數(shù)
    private void setConnectionParams(HttpUriRequest httpUriRequest){
        HttpParams httpParams = httpUriRequest.getParams();
        HttpConnectionParams.setConnectionTimeout(httpParams,mConfig.ConnTimeOut);
        HttpConnectionParams.setSoTimeout(httpParams,mConfig.soTimeOut);
    }
    //根據(jù)類型創(chuàng)建不同的請求類型
    static HttpUriRequest createHttpRequest(Request<?> request){
        HttpUriRequest httpUriRequest = null;
        switch (request.getHttpMethod()){
            case GET:
                httpUriRequest = new HttpGet(request.getUrl());
                break;
            case DELETE:
                httpUriRequest = new HttpDelete(request.getUrl());
                break;
            case POST:
                httpUriRequest = new HttpPost(request.getUrl());
                break;
            case PUT:
                httpUriRequest = new HttpPut(request.getUrl());
                break;
            default:
                throw new IllegalStateException("Unknown request method.");
        }
        return httpUriRequest;
    }

    //添加請求頭
    private static void addHeaders(HttpUriRequest request, Map<String,String> headers){
        for (String key : headers.keySet()){
            request.setHeader(key,headers.get(key));
        }
    }

    //將請求參數(shù)設(shè)置到HttpEntity中
    private static void setEntityNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest,
                                              Request<?> request){
        byte[] body = request.getBody();
        if (body != null){
            HttpEntity entity = new ByteArrayEntity(body);
            httpRequest.setEntity(entity);
        }
    }
}

3. 使用HttpUrlConnStack方式實現(xiàn)請求

/**
 * Created by lq on 2017/5/14.
 * 使用HttpURLConnection執(zhí)行網(wǎng)絡(luò)請求的HttpStack
 */

public class HttpUrlConnStack implements HttpStack {
    //配置https
    HttpUrlConnConfig mConfig = HttpUrlConnConfig.getConfig();

    @Override
    public Response performRequest(Request<?> request) {
        HttpURLConnection connection = null;
        try {
            //構(gòu)建HttpURLConnection
            connection = createUrlConnection(request.getUrl());
            //設(shè)置headers
            setRequestHeaders(connection,request);
            //設(shè)置Body參數(shù)
            setRequestParams(connection,request);
            //https配置
            configHttps(request);
            //獲取結(jié)果
            return fetchResponse(connection);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (connection != null){
                connection.disconnect();
            }
        }
        return null;
    }
    //構(gòu)建連接
    private HttpURLConnection createUrlConnection(String url) throws IOException {
        URL newUrl = new URL(url);
        URLConnection urlConnection = newUrl.openConnection();
        urlConnection.setConnectTimeout(mConfig.ConnTimeOut);
        urlConnection.setReadTimeout(mConfig.soTimeOut);
        urlConnection.setDoInput(true);
        urlConnection.setDoOutput(true);
        return (HttpURLConnection) urlConnection;
    }
    
    private void configHttps(Request<?> request){
        if (request.isHttps()){
            SSLSocketFactory sslFactory = mConfig.getSslSocketFactory();
            if (sslFactory != null){
                HttpsURLConnection.setDefaultSSLSocketFactory(sslFactory);
                HttpsURLConnection.setDefaultHostnameVerifier(mConfig.getHostnameVerifier());
            }
        }
    }

    private void setRequestHeaders(HttpURLConnection connection, Request<?> request){
        Set<String> headerKeys = request.getHeaders().keySet();
        for (String headerName : headerKeys){
            connection.addRequestProperty(headerName,request.getHeaders().get(headerName));
        }
    }
    //將數(shù)據(jù)寫入請求中,針對POST和PUT方式
    protected void setRequestParams(HttpURLConnection connection, Request<?> request) throws IOException {
        Request.HttpMethod method = request.getHttpMethod();
        connection.setRequestMethod(method.toString());
        byte[] body = request.getBody();
        if (body != null){
            connection.setDoOutput(true);
            connection.addRequestProperty(Request.HEADER_CONTENT_TYPE,request.getBodyContentType());
            DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());
            dataOutputStream.write(body);
            dataOutputStream.close();
        }
    }
    //解析響應(yīng),并構(gòu)建自定義響應(yīng)
    private Response fetchResponse(HttpURLConnection connection) throws IOException {
        ProtocolVersion protocolVersion = new ProtocolVersion("HTTP",1,1);
        int responseCode = connection.getResponseCode();
        if (responseCode == -1){
            throw new IOException("Could not retries response code from HttpUrlConnection");
        }
        //狀態(tài)行數(shù)據(jù)
        StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(),
                    connection.getResponseMessage());
        //構(gòu)建response
        Response response = new Response(responseStatus);
        //設(shè)置response數(shù)據(jù)
        response.setEntity(entityFromURLConnection(connection));
        addHeadersToResponse(response,connection);
        return response;
    }

    //執(zhí)行HTTP請求后獲取到其數(shù)據(jù)流疯特,即返回請求結(jié)果的entity對象
    private HttpEntity entityFromURLConnection(HttpURLConnection connection){
        BasicHttpEntity entity = new BasicHttpEntity();
        InputStream is = null;
        try {
            is = connection.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            is = connection.getErrorStream();
        }
        entity.setContent(is);
        entity.setContentLength(connection.getContentLength());
        entity.setContentEncoding(connection.getContentEncoding());
        entity.setContentType(connection.getContentType());
        return entity;
    }
    //將連接的請求頭添加到響應(yīng)中
    private void addHeadersToResponse(BasicHttpResponse response, HttpURLConnection connection){
        for (Map.Entry<String,List<String>> header : connection.getHeaderFields().entrySet()){
            if (header.getKey() != null){
                Header h = new BasicHeader(header.getKey(),header.getValue().get(0));
                response.addHeader(h);
            }
        }
    }
}

4. 根據(jù)SDK選擇不同的請求方式

/**
 * Created by lq on 2017/5/14.
 * 根據(jù)api版本選擇HttpClient或者HttpURLConnection.
 */

public class HttpStackFactory {
    private static final int GINGERBREAD_SDK_NUM = 9;
    public static HttpStack createHttpStack(){
        int runtimeSDKApi = Build.VERSION.SDK_INT;
        if (runtimeSDKApi >= GINGERBREAD_SDK_NUM){
            return new HttpUrlConnStack();
        }
        return new HttpClientStack();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淹办,一起剝皮案震驚了整個濱河市印荔,隨后出現(xiàn)的幾起案子攻询,更是在濱河造成了極大的恐慌澎蛛,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜕窿,死亡現(xiàn)場離奇詭異,居然都是意外死亡呆馁,警方通過查閱死者的電腦和手機桐经,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浙滤,“玉大人阴挣,你說我怎么就攤上這事》睦埃” “怎么了畔咧?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長揖膜。 經(jīng)常有香客問我誓沸,道長,這世上最難降的妖魔是什么壹粟? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任拜隧,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洪添。我一直安慰自己垦页,他們只是感情好,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布干奢。 她就那樣靜靜地躺著痊焊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪忿峻。 梳的紋絲不亂的頭發(fā)上薄啥,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音炭菌,去河邊找鬼罪佳。 笑死,一個胖子當著我的面吹牛黑低,可吹牛的內(nèi)容都是我干的赘艳。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼克握,長吁一口氣:“原來是場噩夢啊……” “哼蕾管!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起菩暗,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掰曾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后停团,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旷坦,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年佑稠,在試婚紗的時候發(fā)現(xiàn)自己被綠了秒梅。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡舌胶,死狀恐怖捆蜀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幔嫂,我是刑警寧澤辆它,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站履恩,受9級特大地震影響锰茉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜切心,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一洞辣、第九天 我趴在偏房一處隱蔽的房頂上張望咐刨。 院中可真熱鬧,春花似錦扬霜、人聲如沸定鸟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽联予。三九已至,卻和暖如春材原,著一層夾襖步出監(jiān)牢的瞬間沸久,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工余蟹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卷胯,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓威酒,卻偏偏與公主長得像窑睁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子葵孤,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,111評論 25 707
  • 國家電網(wǎng)公司企業(yè)標準(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報批稿:20170802 前言: 排版 ...
    庭說閱讀 10,967評論 6 13
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫担钮、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,102評論 4 62
  • 四十多歲了尤仍,去學駕照箫津,確實需要點勇氣。 我的勇氣來源于先生宰啦。他是個極其惰性的人苏遥,什么事都不想干,叫他學駕照赡模,報名了...
    回首己陌路閱讀 186評論 0 1
  • 星漢沐天河暖眼, 輾轉(zhuǎn)難眠客。 依稀冬風起纺裁, 拍我小窗過。 沓沓聞雞鳴司澎。 寂寂寒夜色欺缘。 黃粱夢易醒, 百年似爛柯挤安!
    化繭成蝶_219a閱讀 120評論 0 1