Android网络基础之HttpClient与HttpURLConnection

原创 2016年05月30日 12:58:57

基于面试中常常提及到这二者,我们就来看看Apache的HttpClient和Java的HttpURLConnection的区别 。以后或许对你们有用也说不定。

1.HttpClient
Android SDK中包含了HttpClient,在Android6.0版本直接删除了HttpClient类库,如果仍想使用则解决方法是:
如果使用的是eclipse则在libs中加入org.apache.http.legacy.jar
这个jar包在:**sdk\platforms\android-23\optional目录中(需要下载android
6.0的SDK)
如果使用的是android studio则 在相应的module下的build.gradle中加入:

   android {
       useLibrary 'org.apache.http.legacy'
        } 

HttpClient的GET请求

首先我们来用DefaultHttpClient类来实例化一个HttpClient,并配置好默认的请求参数:

 //创建HttpClient
    private HttpClient createHttpClient() {
        HttpParams mDefaultHttpParams = new BasicHttpParams();
        //设置连接超时
        HttpConnectionParams.setConnectionTimeout(mDefaultHttpParams, 15000);
        //设置请求超时
        HttpConnectionParams.setSoTimeout(mDefaultHttpParams, 15000);
        HttpConnectionParams.setTcpNoDelay(mDefaultHttpParams, true);
        HttpProtocolParams.setVersion(mDefaultHttpParams, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(mDefaultHttpParams, HTTP.UTF_8);
        //持续握手
        HttpProtocolParams.setUseExpectContinue(mDefaultHttpParams, true);
        HttpClient mHttpClient = new DefaultHttpClient(mDefaultHttpParams);
        return mHttpClient;

    }

接下来创建HttpGet和HttpClient,请求网络并得到HttpResponse,并对HttpResponse进行处理:

  private void useHttpClientGet(String url) {
        HttpGet mHttpGet = new HttpGet(url);
        mHttpGet.addHeader("Connection", "Keep-Alive");
        try {
            HttpClient mHttpClient = createHttpClient();
            HttpResponse mHttpResponse = mHttpClient.execute(mHttpGet);
            HttpEntity mHttpEntity = mHttpResponse.getEntity();
            int code = mHttpResponse.getStatusLine().getStatusCode();
            if (null != mHttpEntity) {
                InputStream mInputStream = mHttpEntity.getContent();
                String respose = converStreamToString(mInputStream);
                Log.i("wangshu", "请求状态码:" + code + "\n请求结果:\n" + respose);
                mInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

converStreamToString方法将请求结果转换成String类型:

private String converStreamToString(InputStream is) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuffer sb = new StringBuffer();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        String respose = sb.toString();
        return respose;
    }

最后我们开启线程访问百度:

  new Thread(new Runnable() {
            @Override
            public void run() {
                useHttpClientGet("http://www.baidu.com");
            }
        }).start();

请求的返回结果,请求状态码为200,结果就是个html页,这里只截取了部分html代码:
这里写图片描述

GET请求的参数暴露在URL中,这有些不大妥当,而且URL的长度也有限制:长度在2048字符之内,在HTTP 1.1后URL长度才没有限制。一般情况下POST可以替代GET,接下来我们来看看HttpClient的POST请求。

HttpClient的POST请求

post请求和get类似就是需要配置要传递的参数:

    private void useHttpClientPost(String url) {
        HttpPost mHttpPost = new HttpPost(url);
        mHttpPost.addHeader("Connection", "Keep-Alive");
        try {
            HttpClient mHttpClient = createHttpClient();
            List<NameValuePair> postParams = new ArrayList<>();
            //要传递的参数
            postParams.add(new BasicNameValuePair("username", "moon"));
            postParams.add(new BasicNameValuePair("password", "123"));
            mHttpPost.setEntity(new UrlEncodedFormEntity(postParams));
            HttpResponse mHttpResponse = mHttpClient.execute(mHttpPost);
            HttpEntity mHttpEntity = mHttpResponse.getEntity();
            int code = mHttpResponse.getStatusLine().getStatusCode();
            if (null != mHttpEntity) {
                InputStream mInputStream = mHttpEntity.getContent();
                String respose = converStreamToString(mInputStream);
                Log.i("wangshu", "请求状态码:" + code + "\n请求结果:\n" + respose);
                mInputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2.HttpURLConnection

Android 2.2版本之前,HttpURLConnection一直存在着一些令人厌烦的bug。比如说对一个可读的InputStream调用close()方法时,就有可能会导致连接池失效了。那么我们通常的解决办法就是直接禁用掉连接池的功能:

private void disableConnectionReuseIfNecessary() {
      // 这是一个2.2版本之前的bug
      if (Integer.parseInt(Build.VERSION.SDK) < Build.VERSION_CODES.FROYO) {
            System.setProperty("http.keepAlive", "false");
      }
}

所以在Android 2.2版本以及之前的版本使用HttpClient是较好的选择,而在Android 2.3版本及以后,HttpURLConnection则是最佳的选择,它的API简单,体积较小,因而非常适用于Android项目。压缩和缓存机制可以有效地减少网络访问的流量,在提升速度和省电方面也起到了较大的作用。另外在Android 6.0版本中,HttpClient库被移除了,HttpURLConnection则是以后我们唯一的选择。

HttpURLConnection的POST请求

因为会了HttpURLConnection的POST请求那GET请求也就会了,所以我这里只举出POST的例子
首先我们创建一个UrlConnManager类,然后里面提供getHttpURLConnection()方法用于配置默认的参数并返回HttpURLConnection:

   public static HttpURLConnection getHttpURLConnection(String url){
        HttpURLConnection mHttpURLConnection=null;
        try {
            URL mUrl=new URL(url);
            mHttpURLConnection=(HttpURLConnection)mUrl.openConnection();
            //设置链接超时时间
            mHttpURLConnection.setConnectTimeout(15000);
            //设置读取超时时间
            mHttpURLConnection.setReadTimeout(15000);
            //设置请求参数
            mHttpURLConnection.setRequestMethod("POST");
            //添加Header
            mHttpURLConnection.setRequestProperty("Connection","Keep-Alive");
            //接收输入流
            mHttpURLConnection.setDoInput(true);
            //传递参数时需要开启
            mHttpURLConnection.setDoOutput(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return mHttpURLConnection ;
    }

因为我们要发送POST请求,所以在UrlConnManager类中再写一个postParams()方法用来组织一下请求参数并将请求参数写入到输出流中:

 public static void postParams(OutputStream output,List<NameValuePair>paramsList) throws IOException{
       StringBuilder mStringBuilder=new StringBuilder();
       for (NameValuePair pair:paramsList){
           if(!TextUtils.isEmpty(mStringBuilder)){
               mStringBuilder.append("&");
           }
           mStringBuilder.append(URLEncoder.encode(pair.getName(),"UTF-8"));
           mStringBuilder.append("=");
           mStringBuilder.append(URLEncoder.encode(pair.getValue(),"UTF-8"));
       }
       BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(output,"UTF-8"));
       writer.write(mStringBuilder.toString());
       writer.flush();
       writer.close();
   }

接下来我们添加请求参数,调用postParams()方法将请求的参数组织好传给HttpURLConnection的输出流,请求连接并处理返回的结果:

  private void useHttpUrlConnectionPost(String url) {
        InputStream mInputStream = null;
        HttpURLConnection mHttpURLConnection = UrlConnManager.getHttpURLConnection(url);
        try {
            List<NameValuePair> postParams = new ArrayList<>();
            //要传递的参数
            postParams.add(new BasicNameValuePair("username", "moon"));
            postParams.add(new BasicNameValuePair("password", "123"));
            UrlConnManager.postParams(mHttpURLConnection.getOutputStream(), postParams);
            mHttpURLConnection.connect();
            mInputStream = mHttpURLConnection.getInputStream();
            int code = mHttpURLConnection.getResponseCode();
            String respose = converStreamToString(mInputStream);
            Log.i("wangshu", "请求状态码:" + code + "\n请求结果:\n" + respose);
            mInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

最后开启线程请求网络:

 private void useHttpUrlConnectionGetThread() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                useHttpUrlConnectionPost("http://www.baidu.com");
            }
        }).start();
    }

这里我们仍旧请求百度,看看会发生什么?
这里写图片描述
mInputStream = mHttpURLConnection.getInputStream() 这句代码报错了,找不到文件。打开Fiddler来分析一下,不了解Fiddler和HTTP协议原理的请查看Android网络编程(一)HTTP协议原理这篇文章。

看下我们的请求报文:
这里写图片描述

看来请求报文没有问题,再来看看响应报文:
这里写图片描述
报504错误,读取响应的数据报错,对于我们这次请求服务端不能返回完整的响应,返回的数据为0 bytes,所以mHttpURLConnection.getInputStream() 也读不到服务端响应的输入流。当然这次错误是正常的,百度没理由处理我们的这次POST请求。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Android网络基础之HttpClient与HttpURLConnection

基于面试中常常提及到这二者,我们就来看看Apache的HttpClient和Java的HttpURLConnection的区别 。以后或许对你们有用也说不定。1.HttpClient Android...

android 网络通信之HttpURLConnection与HttpClient

简单来说,用HttpClient发送请求、接收响应都很简单,只需要几个步骤即可: 创建HttpClient对象。 创建对应的发送请求的对象,如果需要发送GET请求,则创建HttpGet对象,如果需要...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

Android网络HttpURLConnection和HttpClient

Android网络HttpURLConnection和HttpClient

Android网络HttpURLConnection和HttpClient

Android网络HttpURLConnection和HttpClient

android 网络编程 - HttpURLConnection与HttpClient

安卓和Java应用开发少不了要提交HTTP请求,而基本上目前有两个实现方式:HttpUrlConnection(即URL.openConnection)和HttpClient。 HttpClient是...

网络<二>httpclient /httpURLConnection

httpclient /httpURLConnection httpclient和httpURLConnection是android早期的网络原生请求类库,httpclient先于httpCon...

Android网络编程(二)HttpClient与HttpURLConnection

 转载:  http://liuwangshu.cn/application/network/2-httpclienthttp-urlconnection.html 1.HttpClie...

Android网络编程(二)HttpClient与HttpURLConnection

上一篇我们了解了HTTP协议原理,这一篇我们来讲讲Apache的HttpClient和Java的HttpURLConnection,这两种都是我们平常请求网络会用到的。无论我们是自己封装的网络请求类还...

Android网络访问之HttpURLConnection和HttpClient

Android 上发送 HTTP 请求的一般有两种方式,HttpURLConnection 和 HttpClient。下面分别简述两种方式的用法。1. HttpURLConnection1, 获取 H...

Android网络编程之HttpUrlConnection、HttpClient

这篇文章我们共同来学习HttpUrlConnection以及HttpClient. 首先,我们来了解一下通过Http协议,Android APP客户端与服务器交互的基本知识 客户端...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)