HttpClient和HttpURLConnection的使用和区别(上)

相信很多Android开发者碰到涉及到Http协议的需求时,都和我一样在犹豫是使用HttpClient还是使用HttpURLConnection呢。我在网上也搜索了很多文章,来分析两者的区别。接下来我们就剖析一下这两个网络开源库,分别从背景、用法、相同点、区别这几点来入手分析。

目录


补充知识


  • TCP/IP、Socket、HTTP简要介绍

    1. TCP/IP中文名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。

    2. Socket是支持TCP/IP协议的网络通信基本操作单元,许多操作系统为应用程序提供了一套调用接口(API),方便开发者开发网络程序。注意,socket本身并不是协议,只是提供一个针对TCP或UDP的编程接口。

    3. HTTP协议是一个web服务器和客户端通信的超文本传送协议,是建立在TCP协议上的一个应用层协议。
      HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

  • HTTP1.0
    客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

  • HTTP1.1
    可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

背景


  • HttpClient

    Apache公司提供的库,提供高效的、最新的、功能丰富的支持HTTP协议工具包,支持HTTP协议最新的版本和建议,是个很不错的开源框架,封装了http的请求,参数,内容体,响应等,拥有众多API。

  • HttpURLConnection

    Sun公司提供的库,也是Java的标准类库java.net中的一员,但这个类什么都没封装,用起来很原始,若需要高级功能,则会显得不太方便,比如重访问的自定义,会话和cookie等一些高级功能。

用法


这两种方式都支持HTTPS协议,以流的形式进行上传和下载,配置超时时间,IPV6,连接池等功能。

HttpClient的用法

一、执行请求

HttpClient最重要的功能是执行HTTP方法。一个HTTP方法的执行包含一个或多个HTTP请求/HTTP响应交流,通常由HttpClient的内部来处理。用户提供一个请求对象,HttpClient发送请求到目标服务器,希望服务器返回一个相应的响应对象,或者抛出一个异常(执行失败)。

一个简单的请求执行过程的示例:

[java]  view plain copy print ?
  1. HttpClient httpclient = new DefaultHttpClient();  
  2. HttpGet httpget = new HttpGet("http://localhost/");  
  3. HttpResponse response = httpclient.execute(httpget);  
  4. HttpEntity entity = response.getEntity();  
  5. if (entity != null) {  
  6.     InputStream instream = entity.getContent();  
  7.     int l;  
  8.     byte[] tmp = new byte[2048];  
  9.     while ((l = instream.read(tmp)) != -1) {  
  10.     }  
  11. }  
二、用工具封装Get请求

对比下面两段代码,发现用httpClient提供的方法更具可读性

[java]  view plain copy print ?
  1. HttpGet httpget = new HttpGet(  
  2. "http://www.google.com/search?hl=en&q=httpclient&btnG=Google+Search&aq=f&oq=");  

HttpClient提供很多工具方法来简化创建和修改执行URI,例如:

[java]  view plain copy print ?
  1. List<NameValuePair> qparams = new ArrayList<NameValuePair>();  
  2. qparams.add(new BasicNameValuePair("q""httpclient"));  
  3. qparams.add(new BasicNameValuePair("btnG""Google Search"));  
  4. qparams.add(new BasicNameValuePair("aq""f"));  
  5. qparams.add(new BasicNameValuePair("oq"null));  
  6. URI uri = URIUtils.createURI("http""www.google.com", -1"/search",  
  7. URLEncodedUtils.format(qparams, "UTF-8"), null);  
  8. HttpGet httpget = new HttpGet(uri);  
三、处理头部消息

一个HTTP消息可以包含一系列头部描述消息的属性。例如:内容长度、内容类型等。

HttpClient提供方法检索、添加、删除、枚举头部信息。

[java]  view plain copy print ?
  1. HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus.SC_OK, "OK");  
  2. response.addHeader("Set-Cookie","c1=a; path=/; domain=localhost");  
  3. response.addHeader("Set-Cookie","c2=b; path=/; domain=localhost");  
  4. //获取header的方法1  
  5. Header h1 = response.getFirstHeader("Set-Cookie");  
  6. Header h2 = response.getLastHeader("Set-Cookie");  
  7. //获取header的方法2  
  8. HeaderIterator it = response.headerIterator("Set-Cookie");  
  9. while (it.hasNext()) {  
  10.     System.out.println(it.next());  
  11. }  
  12. //获取header的方法3  
  13. Header[] headers = response.getAllHeaders();  
  14. for (Header header : headers) {  
  15.     System.out.println(header.getName() + " | " + header.getValue());  
  16. }  
四、HTTP实体

HTTP规范定义了两种包装实体的方法:POST和PUT。响应通常附上内容实体。

HttpClient根据其内容出自何处区分三种类型的实体:

  1. streamed(流式):内容从流中获得,或者在运行中产生。流式实体是不可重复生成的。

  2. self-contained(自我包装式):内容在内存中或通过独立的连接或其它实体中获得。自我包装式的实体是可以重复生成和读取的。经常用于封装HTTP请求实体。(像ByteArrayEntity或StringEntity)。

  3. wrapping(包裹式):内容从另外一个实体中获得。

如果从一个HTTP响应中获取流式内容,这个区别对于连接管理很重要。

如果是应用程序创建并用于发送的请求实体,这个类型区别就没那么重要了。

五、使用HTTP实体

使用实体常用的一些API,得到内容类型、内容长度、内容编码、内容转换成String或ByteArray、设置分块(HTTP1.1)。但是,EntityUtils的使用是不鼓励的,除非实体响应来自一个可信赖的HTTP服务器和已知的有限长度。

[java]  view plain copy print ?
  1. myEntity.getContentType()  
  2. myEntity.getContentLength()  
  3. EntityUtils.getContentCharSet(myEntity)  
  4. EntityUtils.toString(myEntity)  
  5. EntityUtils.toByteArray(myEntity)  
  6. myEntity.setChunked(true);  
六、得到实体内容

[java]  view plain copy print ?
  1. HttpGet httpget = new HttpGet("http://localhost/");  
  2. HttpResponse response = httpclient.execute(httpget);  
  3. HttpEntity entity = response.getEntity();  
  4. if (entity != null) {  
  5.     long len = entity.getContentLength();  
  6.     if (len != -1 && len < 2048) {  
  7.         System.out.println(EntityUtils.toString(entity));  
  8.     } else {  
  9.         InputStream instream = entity.getContent();  
  10.         int byteOne = instream.read();  
  11.         int byteTwo = instream.read();  
  12.         //终止请求,该连接将不被重用,保证底层的资源被正确释放  
  13.         httpget.abort();  
  14.     }  
  15. }  


七、生成实体内容

HttpClient提供了常见的数据容器,比如字符串,字节数组,输入流和文件:StringEntity,ByteArrayEntity,InputStreamEntity和FileEntity。

[java]  view plain copy print ?
  1. File file = new File("somefile.txt");  
  2. FileEntity entity = new FileEntity(file, "text/plain; charset=\"UTF-8\"");  
  3. HttpPost httppost = new HttpPost("http://localhost/action.do");  
  4. httppost.setEntity(entity);  


八、HTML表单(UrlEncodedFormEntity)

许多应用程序需要频繁模拟提交一个HTML表单的过程,比如,为了来记录一个Web应用程序或提交输出数据。HttpClient提供了特殊的实体类UrlEncodedFormEntity来这个满足过程。


[java]  view plain copy print ?
  1. List<NameValuePair> formparams = new ArrayList<NameValuePair>();  
  2. formparams.add(new BasicNameValuePair("param1""value1"));  
  3. formparams.add(new BasicNameValuePair("param2""value2"));  
  4. //生成的实体内容:param1=value1¶m2=value2  
  5. UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");  
  6. HttpPost httppost = new HttpPost("http://localhost/handler.do");  
  7. httppost.setEntity(entity);  


九、响应处理器(ResponseHandler)

ResponseHandler能够保证在任何情况下都会将底层的HTTP连接释放回连接管理器。用户不必担心HttpClient连接占用系统资源,可以把注意力集中在处理HTTP响应内容。


[java]  view plain copy print ?
  1. HttpClient httpclient = new DefaultHttpClient();  
  2. HttpGet httpget = new HttpGet("http://localhost/");  
  3. ResponseHandler<byte[]> handler = new ResponseHandler<byte[]>() {  
  4.     public byte[] handleResponse(HttpResponse response) throws ClientProtocolException, IOException {  
  5.         HttpEntity entity = response.getEntity();  
  6.         if (entity != null) {  
  7.             return EntityUtils.toByteArray(entity);  
  8.         } else {  
  9.             return null;  
  10.         }  
  11.     }  
  12. };  
  13. byte[] response = httpclient.execute(httpget, handler);  


HttpClient还提供了很多高级的特性,如:连接管理、状态管理、认证管理、客户服务等。这里只介绍了一些基础的用法,有时间好好研究一下,再专门写一篇关于HttpClient的博客。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值