Android--Apache HttpClient(2种实现)
前言
上一篇文章介绍了使用HttpURLConnection来完成对于HTTP协议的支持,现在介绍一个新的方式来访问Web站点,那就是HttpClient。
HttpClient是Apache开源组织提供的一个开源的项目,从名字上就可以看出,它是一个简单的HTTP客户端(并不是浏览器),可以发送HTTP请求,接受HTTP响应。但是不会缓存服务器的响应,不能执行HTTP页面中签入嵌入的JS代码,自然也不会对页面内容进行任何解析、处理,这些都是需要开发人员来完成的。
现在Android已经成功集成了HttpClient,所以开发人员在Android项目中可以直接使用HttpClient来想Web站点提交请求以及接受响应,如果使用其他的Java项目,需要引入进相应的Jar包。HttpClient可以在官网上下载。
HttpClient
HttpClient其实是一个interface类型,HttpClient封装了对象需要执行的Http请求、身份验证、连接管理和其它特性。从文档上看,HttpClient有三个已知的实现类分别是:AbstractHttpClient, AndroidHttpClient, DefaultHttpClient,会发现有一个专门为Android应用准备的实现类AndroidHttpClient,当然使用常规的DefaultHttpClient也可以实现功能,但是既然开发的是Android应用程序,还是使用Android专有的实现类,一定有其优势。
从两个类包所有在位置就可以看出区别,AndroidHttpClient定义在android.net.http.AndroidHttpClient包下,属于Android原生的http访问,而DefaultHttpClient定义在org.apache.http.impl.client.DefaultHttpClient包下,属于对apche项目的支持。而AndroidHttpClient没有公开的构造函数,只能通过静态方法newInstance()方法来获得AndroidHttpClient对象。
AndroidHttpClient对于DefaultHttpClient做了一些改进,使其更使用用于Android项目:
- 关掉过期检查,自连接可以打破所有的时间限制。
- 可以设置ConnectionTimeOut(连接超时)和SoTimeout(读取数据超时)。
- 关掉重定向。
- 使用一个Session缓冲用于SSL Sockets。
- 如果服务器支持,使用gzip压缩方式用于在服务端和客户端传递的数据。
- 默认情况下不保留Cookie。
简单来说,用HttpClient发送请求、接收响应都很简单,只需要几个步骤即可:
- 创建HttpClient对象。
- 创建对应的发送请求的对象,如果需要发送GET请求,则创建HttpGet对象,如果需要发送POST请求,则创建HttpPost对象。
- 对于发送请求的参数,GET和POST使用的方式不同,GET方式可以使用拼接字符串的方式,把参数拼接在URL结尾;POST方式需要使用setEntity(HttpEntity entity)方法来设置请求参数。
- 调用HttpClient对象的execute(HttpUriRequest request)发送请求,执行该方法返回一个HttpResponse对象。
- 调用HttpResponse的对应方法获取服务器的响应头、响应内容等。
DefaultHttpClient
先看看使用DefaultHttpClient方式发送Web站点请求,上面已经简要说明了步骤,在这里简要说明一个参数的传递问题,对于GET方式,只需要拼接字符串就在URL结尾即可,但是对于POST方式,需要传递HttpEntity对象,HttpEntity为一个接口,有多个实现类,可以使用其间接子继承,UrlEncodedFormEntity类来保存请求参数,并传递给HttpPost。
此例子简单实现了在Android客户端使用DefaultHttpClient实现一个Http站点登陆的实现,使用的是POST传递,其传递值只需要传递username+password即可,当传递的数据为admin+123则认为登陆成功。Web站点使用.net的架构,一个一般处理程序,简单的比对账户密码,这里就不在此讲解。
因为Android4.0之后对使用网络有特殊要求,已经无法再在主线程中访问网络了,必须使用多线程访问的模式,其他的一些信息在代码注释中已经说明。
DefaultHttpClient-Code
1 package com.bgxt.httpUtils;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.UnsupportedEncodingException;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.apache.http.HttpResponse;
13 import org.apache.http.NameValuePair;
14 import org.apache.http.client.ClientProtocolException;
15 import org.apache.http.client.entity.UrlEncodedFormEntity;
16 import org.apache.http.client.methods.HttpPost;
17 import org.apache.http.impl.client.DefaultHttpClient;
18 import org.apache.http.message.BasicNameValuePair;
19
20 public class httpClientUtils implements Runnable {
21 /**
22 * 对于Android4.0之上的环境下,不能在主线程中访问网络 所以这里另新建了一个实现了Runnable接口的Http访问类
23 */
24 private String username;
25 private String password;
26
27 public httpClientUtils(String username, String password) {
28 // 初始化用户名和密码
29 this.username = username;
30 this.password = password;
31 }
32
33 @Override
34 public void run() {
35 // 设置访问的Web站点
36 String path = "http://192.168.1.103:1231/loginas.ashx";
37 // 设置Http请求参数
38 Map<String, String> params = new HashMap<String, String>();
39 params.put("username", username);
40 params.put("password", password);
41
42 String result = sendHttpClientPost(path, params, "utf-8");
43 // 把返回的接口输出
44 System.out.println(result);
45 }
46
47 /**
48 * 发送Http请求到Web站点
49 *
50 * @param path
51 * Web站点请求地址
52 * @param map
53 * Http请求参数
54 * @param encode
55 * 编码格式
56 * @return Web站点响应的字符串
57 */
58 private String sendHttpClientPost(String path, Map<String, String> map,
59 String encode) {
60 List<NameValuePair> list = new ArrayList<NameValuePair>();
61 if (map != null && !map.isEmpty()) {
62 for (Map.Entry<String, String> entry : map.entrySet()) {
63 // 解析Map传递的参数,使用一个键值对对象BasicNameValuePair保存。
64 list.add(new BasicNameValuePair(entry.getKey(), entry
65 .getValue()));
66 }
67 }
68 try {
69 // 实现将请求 的参数封装封装到HttpEntity中。
70 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list, encode);
71 // 使用HttpPost请求方式
72 HttpPost httpPost = new HttpPost(path);
73 // 设置请求参数到Form中。
74 httpPost.setEntity(entity);
75 // 实例化一个默认的Http客户端
76 DefaultHttpClient client = new DefaultHttpClient();
77 // 执行请求,并获得响应数据
78 HttpResponse httpResponse = client.execute(httpPost);
79 // 判断是否请求成功,为200时表示成功,其他均问有问题。
80 if (httpResponse.getStatusLine().getStatusCode() == 200) {
81 // 通过HttpEntity获得响应流
82 InputStream inputStream = httpResponse.getEntity().getContent();
83 return changeInputStream(inputStream, encode);
84 }
85 } catch (UnsupportedEncodingException e) {
86 e.printStackTrace();
87 } catch (ClientProtocolException e) {
88 e.printStackTrace();
89 } catch (IOException e) {
90 e.printStackTrace();
91 }
92 return "";
93 }
94
95 /**
96 * 把Web站点返回的响应流转换为字符串格式
97 *
98 * @param inputStream
99 * 响应流
100 * @param encode
101 * 编码格式
102 * @return 转换后的字符串
103 */
104 private String changeInputStream(InputStream inputStream, String encode) {
105 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106 byte[] data = new byte[1024];
107 int len = 0;
108 String result = "";
109 if (inputStream != null) {
110 try {
111 while ((len = inputStream.read(data)) != -1) {
112 outputStream.write(data, 0, len);
113 }
114 result = new String(outputStream.toByteArray(), encode);
115
116 } catch (IOException e) {
117 e.printStackTrace();
118 }
119 }
120 return result;
121 }
122
123 }
AndroidHttpClient
使用AndroidHttpClient的方式和DefaultHttpClient差不多,不多的几点区别上面已经说明,但是在此例子中没有体现。有一点需要注意的是,AndroidHttpClient是一个final类,也没有公开的构造函数,所以无法使用new的形式对其进行实例化,必须使用AndroidHttpClient.newInstance()方法获得AndroidHttpClient对象。
示例中依然是使用POST请求,实现的功能和DefaultHttpClient示例一样。细节部分已经在注释中体现,直接看代码即可。
1 package com.bgxt.httpUtils;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.UnsupportedEncodingException;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.Map;
11
12 import org.apache.http.HttpResponse;
13 import org.apache.http.NameValuePair;
14 import org.apache.http.client.ClientProtocolException;
15 import org.apache.http.client.HttpClient;
16 import org.apache.http.client.entity.UrlEncodedFormEntity;
17 import org.apache.http.client.methods.HttpPost;
18 import org.apache.http.impl.client.DefaultHttpClient;
19 import org.apache.http.message.BasicNameValuePair;
20
21 import android.net.http.AndroidHttpClient;
22
23 public class AndroidHttpClientUtils implements Runnable {
24
25 private String username;
26 private String password;
27
28 public AndroidHttpClientUtils(String username, String password) {
29 // 初始化用户名和密码
30 this.username = username;
31 this.password = password;
32 }
33
34 @Override
35 public void run() {
36 // 设置访问的Web站点
37 String path = "http://192.168.1.103:1231/loginas.ashx";
38 //设置Http请求参数
39 Map<String, String> params = new HashMap<String, String>();
40 params.put("username", username);
41 params.put("password", password);
42
43 String result = sendHttpClientPost(path, params, "utf-8");
44 //把返回的接口输出
45 System.out.println(result);
46 }
47 /**
48 * 发送Http请求到Web站点
49 * @param path Web站点请求地址
50 * @param map Http请求参数
51 * @param encode 编码格式
52 * @return Web站点响应的字符串
53 */
54 private String sendHttpClientPost(String path,Map<String, String> map,String encode)
55 {
56 List<NameValuePair> list=new ArrayList<NameValuePair>();
57 if(map!=null&&!map.isEmpty())
58 {
59 for(Map.Entry<String, String> entry:map.entrySet())
60 {
61 //解析Map传递的参数,使用一个键值对对象BasicNameValuePair保存。
62 list.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
63 }
64 }
65 try {
66 //实现将请求 的参数封装封装到HttpEntity中。
67 UrlEncodedFormEntity entity=new UrlEncodedFormEntity(list, encode);
68 //使用HttpPost请求方式
69 HttpPost httpPost=new HttpPost(path);
70 //设置请求参数到Form中。
71 httpPost.setEntity(entity);
72 //实例化一个默认的Http客户端,使用的是AndroidHttpClient
73 HttpClient client=AndroidHttpClient.newInstance("");
74 //执行请求,并获得响应数据
75 HttpResponse httpResponse= client.execute(httpPost);
76 //判断是否请求成功,为200时表示成功,其他均问有问题。
77 if(httpResponse.getStatusLine().getStatusCode()==200)
78 {
79 //通过HttpEntity获得响应流
80 InputStream inputStream=httpResponse.getEntity().getContent();
81 return changeInputStream(inputStream,encode);
82 }
83
84 } catch (UnsupportedEncodingException e) {
85 // TODO Auto-generated catch block
86 e.printStackTrace();
87 } catch (ClientProtocolException e) {
88 // TODO Auto-generated catch block
89 e.printStackTrace();
90 } catch (IOException e) {
91 // TODO Auto-generated catch block
92 e.printStackTrace();
93 }
94
95 return "";
96 }
97 /**
98 * 把Web站点返回的响应流转换为字符串格式
99 * @param inputStream 响应流
100 * @param encode 编码格式
101 * @return 转换后的字符串
102 */
103 private String changeInputStream(InputStream inputStream,
104 String encode) {
105 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
106 byte[] data = new byte[1024];
107 int len = 0;
108 String result="";
109 if (inputStream != null) {
110 try {
111 while ((len = inputStream.read(data)) != -1) {
112 outputStream.write(data,0,len);
113 }
114 result=new String(outputStream.toByteArray(),encode);
115
116 } catch (IOException e) {
117 e.printStackTrace();
118 }
119 }
120 return result;
121 }
122 }
在本文的示例中,环境是使用的Android项目,可以对其进行简单的界面布局,如图:
如果输入用户和密码为:admin+123,则可以再LogCat中查看到登录成功。
总结
最近的两次博客中,已经分别介绍了HttpUrlConnection和HttpClient两种方式,通过Http协议对Web站点的访问。如果还不了解HttpURLConnection的读者,可以看看Android--Http协议。
根据官方文档上说的显示,Android包括两个Http客户端:HttpURLConnection和Apache HttpClient。并且都支持HTTPS,流媒体上传下载,并且可配置超时以及支持IPv6和连接池技术。但是因为移动设备的局限性,HttpURLConnection会是比Apache Http更好的选择,因为其API简单,运行消耗内存小,并且具有公开化的压缩算法,以及响应缓存,能更好的减少网络使用,提供运行速度和节省电池。
但是也不能否认Apache HttpClient,它有大量的灵活的API,实现比较稳定,少有Bug,可造成的问题就是很难在不影响其兼容性的情况下对其进行改进了。现在Android开发者已经慢慢放弃Apache HttpClient的使用,转而使用HttpURLConnection。但是对于Android2.2之前的版本,HttpURLConnection具有一个致命的BUG,在响应输入流InputStream中调用.Close()方法将会阻碍连接池,因为这个BUG,只能放弃连接池的使用,但是Apache HttpClient不存在这个问题,当然Android2.3之后的版本中,HttpURLConnection已经解决了这个BUG,可以放心使用。
Android--Apache HttpClient(2种实现)的更多相关文章
- 在android 6.0(API 23)中,Google已经移除了移除了Apache HttpClient相关的类
推荐使用HttpUrlConnection,如果要继续使用需要Apache HttpClient,需要在eclipse下libs里添加org.apache.http.legacy.jar,androi ...
- Android 6.0删除Apache HttpClient相关类的解决方法
相应的官方文档如下: 上面文档的大致意思是,在Android 6.0(API 23)中,Google已经移除了Apache HttpClient相关的类,推荐使用HttpUrlConnection. ...
- android 中对apache httpclient及httpurlconnection的选择
在官方blog中,android工程师谈到了如何去选择apache client和httpurlconnection的问题: 原文见http://android-developers.blogspot ...
- Android 数据存储五种方式
1.概述 Android提供了5种方式来让用户保存持久化应用程序数据.根据自己的需求来做选择,比如数据是否是应用程序私有的,是否能被其他程序访问,需要多少数据存储空间等,分别是: ① 使用Shared ...
- Android使用HttpClient请求服务器代码优化版
首先,我在前面的两篇博文中介绍了在Android中,除了使用java.net包下HttpUrlConnection的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附 ...
- Android系统的五种数据存储形式(二)
之前介绍了Android系统下三种数据存储形式,今天补充介绍另外两种,分别是内容提供者和网络存储.有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所 ...
- 使用搜狐Sendcloud的Webapi发送邮件:Jodd和Apache Httpclient
最近,在使用搜狐Sendcloud发邮件. Sendcloud提供http格式的webapi,方便地发送邮件,当然是要付费的. 很早之前,http工具一直用Httpclient,后来觉得jodd ...
- 如何在Apache HttpClient中设置TLS版本
1.简介 Apache HttpClient是一个底层.轻量级的客户端HTTP库,用于与HTTP服务器进行通信. 在本教程中,我们将学习如何在使用HttpClient时配置支持的传输层安全(TLS)版 ...
- Apache HttpClient 5 使用详细教程
点赞再看,动力无限. 微信搜「程序猿阿朗 」. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. 超文本传输协议(HTTP)可能是当今 ...
- Android系统的五种数据存储形式(一)
Android系统有五种数据存储形式,分别是文件存储.SP存储.数据库存储.contentprovider 内容提供者.网络存储.其中,前四个是本地存储.存储的类型包括简单文本.窗口状态存储.音频视频 ...
随机推荐
- linux命令之高级使用 service
service命令,顾名思义,就是用于管理Linux操作系统中服务的命令. 1. 声明:这个命令不是在所有的linux发行版本中都有.主要是在redhat.fedora.mandriva和centos ...
- Ubuntu 启动项、菜单 改动 防止隐藏
因为电脑有多个系统,默认的grub引引导菜单是隐藏的,须要略微改动下方可显示 不要直接改动boot/grub/grub.cfg 要直接改动/etc/default/grub,然后update-gru ...
- Check the difficulty of problems - poj 2151 (概率+DP)
有 T(1<T<=1000) 支队伍和 M(0<M<=30) 个题目,已知每支队伍 i 解决每道题目 j 的的概率 p[i][j],现在问:每支队伍至少解决一道题,且解题最多的 ...
- node.js安装与入门使用
一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 的包管理器 npm,是全球最大的开源库生态系统. 提供事件驱动和非阻塞I/O API,可优化应用程序的吞吐量和规 ...
- PAT002 Reversing Linked List
题目: Given a constant K and a singly linked list L, you are supposed to reverse the links of every K ...
- Vector类与Enumeration接口
Vector类用于保存一组对象,由于java不支持动态数组,Vector可以用于实现跟动态数组差不多的功能.如果要将一组对象存放在某种数据结构中,但是不能确定对象的个数时,Vector是一个不错的选择 ...
- 【vijos】1750 建房子(线段树套线段树+前缀和)
https://vijos.org/p/1750 是不是我想复杂了.... 自己yy了个二维线段树,然后愉快的敲打. 但是wa了两法.......sad 原因是在处理第二维的更新出现了个小问题,sad ...
- VUE:使用vue-cli脚手架无法安装npm install axios 的巨坑
使用命令 npm install axios 安装axios可能会报错,无法引用, 这个时候使用淘宝的镜像cnpm安装就可以了 cnpm install axios 如果没有安装cnpm,执行以下命令 ...
- chrome vim设置
chrome vi 插件:Vrome 配置文件如下 set hintkeys=asdfghjkl;" 把默认使用数字来完成提示改为使用键盘上的这几个键map j 10jmap k 10k&q ...
- Python相对完美的URL拼接函数
首先说下什么叫URL拼接,我们有这么一个HTML片段: <a href="../../a.html">click me</a> 做为一只辛苦的爬虫,我们 ...