美文网首页
实现一个简单的网络框架之连接篇

实现一个简单的网络框架之连接篇

作者: 大海孤了岛 | 来源:发表于2017-05-16 14:02 被阅读14次

    实现连接网络并获取数据

    1. 定义一个HttpStack接口

    /**
     * Created by lq on 2017/5/14.
     * 该接口定义了实现请求的具体方法
     */
    public interface HttpStack {
        //真正实现网络请求,并返回数据的方法
        public Response performRequest(Request<?> request);
    }
    

    2. 使用HttpClientStack方式实现请求

    /**
     * Created by lq on 2017/5/14.
     * api 9以下使用HttpClient执行网络请求
     */
    
    public class HttpClientStack implements HttpStack {
        //使用HttpClient执行网络请求的https配置
        HttpClientConfig mConfig = HttpClientConfig.getConfig();
    
        HttpClient mHttpClient = AndroidHttpClient.newInstance(mConfig.userAgent);
    
        @Override
        public Response performRequest(Request<?> request) {
            try {
                HttpUriRequest httpUriRequest = createHttpRequest(request);
                //添加连接参数
                setConnectionParams(httpUriRequest);
                //添加Header
                addHeaders(httpUriRequest,request.getHeaders());
                //https配置
                configHttps(request);
                //执行网络请求,并返回结果
                HttpResponse response = mHttpClient.execute(httpUriRequest);
                //构建Response
                Response rawResponse = new Response(response.getStatusLine());
                //设置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);
            }
        }
        //设置连接参数
        private void setConnectionParams(HttpUriRequest httpUriRequest){
            HttpParams httpParams = httpUriRequest.getParams();
            HttpConnectionParams.setConnectionTimeout(httpParams,mConfig.ConnTimeOut);
            HttpConnectionParams.setSoTimeout(httpParams,mConfig.soTimeOut);
        }
        //根据类型创建不同的请求类型
        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));
            }
        }
    
        //将请求参数设置到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方式实现请求

    /**
     * Created by lq on 2017/5/14.
     * 使用HttpURLConnection执行网络请求的HttpStack
     */
    
    public class HttpUrlConnStack implements HttpStack {
        //配置https
        HttpUrlConnConfig mConfig = HttpUrlConnConfig.getConfig();
    
        @Override
        public Response performRequest(Request<?> request) {
            HttpURLConnection connection = null;
            try {
                //构建HttpURLConnection
                connection = createUrlConnection(request.getUrl());
                //设置headers
                setRequestHeaders(connection,request);
                //设置Body参数
                setRequestParams(connection,request);
                //https配置
                configHttps(request);
                //获取结果
                return fetchResponse(connection);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (connection != null){
                    connection.disconnect();
                }
            }
            return null;
        }
        //构建连接
        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));
            }
        }
        //将数据写入请求中,针对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();
            }
        }
        //解析响应,并构建自定义响应
        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");
            }
            //状态行数据
            StatusLine responseStatus = new BasicStatusLine(protocolVersion, connection.getResponseCode(),
                        connection.getResponseMessage());
            //构建response
            Response response = new Response(responseStatus);
            //设置response数据
            response.setEntity(entityFromURLConnection(connection));
            addHeadersToResponse(response,connection);
            return response;
        }
    
        //执行HTTP请求后获取到其数据流,即返回请求结果的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;
        }
        //将连接的请求头添加到响应中
        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. 根据SDK选择不同的请求方式

    /**
     * Created by lq on 2017/5/14.
     * 根据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();
        }
    }
    

    相关文章

      网友评论

          本文标题:实现一个简单的网络框架之连接篇

          本文链接:https://www.haomeiwen.com/subject/uedlxxtx.html