第13.2.3讲 HTTPClient的简易用法
1 HttpClient简介
1.1 背景
(1.1.1)在访问有些网站和网站提供的某些API时,只有登录成功或者认证授权的才能继续使用,譬如:支付宝第三方接口、工行网银第三方接口等;
(1.1.2)其中最常用的技术实现是通过Session和CookIe保留会话状态,页面切换或站内子功能地址切换时,验证Session或CookIes中的身份等关键信息;
(1.1.3)为了满足会话验证机制的需求,Android集成了由Apache提供的HttpClient封装类;由于其强劲的功能和稳定性,得到了安卓程序员的一致采用;
1.2 HttpClient概述
(1.2.1)HttpClient是由第三方机构Apache开发提供、Android 集成,是客户端的HTTP通信实现库;
(1.2.2)HttpClient顾名思义它是一个简单的HTTP客户端,不是浏览器;
(1.2.3)它可以用于发送HTTP请求,接收HTTP响应;
(1.2.4)不能执行HTML页面代码中的JavaScript代码,也不会对页面进行任何的解析、处理;
(1.2.5)HttpClient不会去缓存内容;
(1.2.6)HttpClient的网络连接是通过底层的网络连接池管理;当完成一个响应实体,所用的连接就安全的放回到连接池中;
(1.2.7)HttpClient可以理解为一个具有会话功能的加强版HttpURLConnection;
(1.2.8)因为HttpClient具有会话功能,因此HttpClient的一个实例可以多次执行不同的HttpPost或HttpGet的请求访问;所以有人把HttpClient的实例放到Application的实例中创建和释放;
1.3 Http协议报文格式重温
(1.3.1)请求报文格式:请求行 + 通用信息头 + 请求头 + 实体头 + 报文主体;
(1.3.2)应答报文格式:状态行 + 通用信息头 + 响应头 + 实体头 + 报文主体;
1.4 讲解说明
由于HttpClient内部处理机制过于复杂,HttpClient成熟的商业级应用流程不是一日之功能掌握的,至今为止网上能把这一个流程做一个详尽讲解的聊聊无几,因为大家都不愿做费力而不落好的事。鉴于此因,我们把HttpClient的应用分成多讲进行; 2 .HttpClient
2.1 构成
(2.1.1)HttpClient是由一组相关的支持类构成其应用体系;包括:HttpClient、HttpGet、HttpPost、HttpParams、HttpResponse、HttpEntity组成;
(2.1.2)HttpClient是一个客户端、稳坐中军帐;通过new DefaultHttpClient()方式构造实例;
(2.1.3)HttpGet是一个封装了的Get;可以通过new HttpGet(String urlStr)方式构造实例;
(2.1.4)HttpPost是一个封装了的Post;可以通过new HttpPost(String urlStr)方式构造实例;
(2.1.5)HttpParams则是一个POST的参数封装类;可以通过 new ArrayList ()方式构造实例;如果参数中有中文,必需通过一个转码函数处理;示例如下:
HttpPost post = new HttpPost("
http://192.168"
+ ".1.88:8888/foo/login.jsp");//③
// 如果传递参数个数比较多的话可以对传递的参数进行封装
List params = new ArrayList();
params.add(new BasicNameValuePair("userName", “张飞”));
params.add(new BasicNameValuePair("userPass", “123321”));
params.add(new BasicNameValuePair("loginGroup", “system”));
//参数强制转码,然后设置post的Entity中的参数
post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
(2.1.6)HttpResponse是服务器端返回内容的一个封装;可以通过HttpClient.execute(post或get)方式获得;
(2.1.6)HttpResponse是服务器端返回内容的一个封装;可以通过HttpClient.execute(post或get)方式获得;
(2.1.6.1)通过HttpResponse可以读取HTTP报文中的状态行类单元;例如:
System.out.println(response.getProtocolVersion());
System.out.println(response.getStatusLine().getStatusCode());
System.out.println(response.getStatusLine().getReasonPhrase());
//显示内容如下依次是: HTTP/1.1 ; 200 ; OK
(2.1.6.2)通过HttpResponse可以读取HTTP报文中的通用信息头单元;例如:
Header[] headers = response.getAllHeaders();
//显示一下返回的头字段,大家可以学习一下都有哪些扩展属性
for (Header item : headers)
{
mResultText+= item.getName() + " --> " + item.getValue()+"\r\n";
}
(2.1.6.3)通过HttpResponse可以读取HTTP报文中的实体部分,见下面实体部分:
(2.1.7)HttpEntit则是实体类,在发送和回应中都有使用;例如POST中的参数设置,主机回复的实体内容(可以是字符串、文本流、字节流、或者多合单元);例如;
HttpClient hc = new DefaultHttpClient();
try {
HttpResponse ht = hc.execute(httpPost);
if(ht.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
HttpEntity het = ht.getEntity();
InputStream is = het.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String response = "";
String readLine = null;
while((readLine =br.readLine()) != null){
response = response + readLine;
}
is.close();
br.close();
//System.out.println("========="+response);
return response;
}else{
return "";
}
}
2.2 简易使用流程
步骤 | GET | POST |
---|---|---|
实例HttpClient | new DefaultHttpClient() | new DefaultHttpClient() |
URL连接串 | 主地址串+?+参数串 | 主地址串 |
实例methods | new HttpGet(uriStr); | post=new HttpPost(uriStr); |
设置头域 | mClient.getParams().setParameter( "http.connection.timeout", Integer.valueOf(10000)); mClient.getParams().setParameter("http.socket.timeout", Integer.valueOf(10000)); | mClient.getParams().setParameter( "http.connection.timeout", Integer.valueOf(10000)); mClient.getParams().setParameter("http.socket.timeout", Integer.valueOf(10000)); |
输出参数 | -- | post.setEntity(new UrlEncodedFormEntity(parmsList,HTTP.UTF_8)); |
连接服务器 | HttpResponse response = httpClient.execute(get); | HttpResponse response = httpClient.execute(post); |
解析响应码 | response.getStatusLine().getStatusCode(); response.getStatusLine().getReasonPhrase() | response.getStatusLine().getStatusCode(); response.getStatusLine().getReasonPhrase() |
解析头域 | get.getAllHeaders() | get.getAllHeaders() |
解析输入流 | br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); | br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); |
释放资源 | 释放流资源;网络连接资源系统自行管理 | 释放流资源;网络连接资源系统自行管理 |
3. 小案例代码
public class HttpClientDangDangClientActivity extends Activity {
private Button btnGet;
private Button btnPost;
private TextView tvContent;
//注意此处 全局的httpClient
private HttpClient httpClient;
//主线程跟子线程之间必需通过Handler通信
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
tvContent.append(msg.obj.toString());
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//创建HttpClient对象
httpClient = getHttpClient();
btnGet = (Button)findViewById(R.id.btnGet);
btnPost = (Button)findViewById(R.id.btnPost);
tvContent = (TextView)findViewById(R.id.tvContent);
//添加单击事件监听器
btnPost.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//实现POST请求
new Thread(){
public void run() {
//发送POST请求具体业务过程
getUserInforByPost("
http://10.0.2.2/DangDang/la", "uid=test&pwd=123456");
}
}.start();
}
});
btnGet.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//发送GET请求
new Thread(){
public void run() {
//具体的请求过程
getUserInforByGet("
http://10.0.2.2/DangDang/la" , "uid=test&pwd=123456);
}
}.start();
}
});
}
/***
*此方法用于获取一个HttpClient的实例
*/
private HttpClient getHttpClient(){
//获取一个HttpClient的实例
HttpClient httpClient=new DefaultHttpClient();
//设置基本的通信参数
httpClient.getParams().setParameter(
"http.connection.timeout", Integer.valueOf(10000));
httpClient.getParams().setParameter("http.socket.timeout",
Integer.valueOf(10000));
}
/**
* 此方法用于发送POST请求
* @param String uri 表示服务程序
* @param String params 表示请求字符串
* @return String 返回响应信息
*/
public String getUserInforByPost(String uri , String params){
//创建一个输入流对象
BufferedReader br = null;
//创建用于存储所有响应信息的字符串
String allContent = "";
//创建HttpClient对象
//创建一个HttpPost对象
HttpPost post = new HttpPost(uri);
//设置请求参数setEntity()
//参数值对构成的集合
List list = new ArrayList();
//参数值对对象
String[] values = params.split("&");
for(String value:values){
list.add(new BasicNameValuePair(value.substring(0, value.indexOf("=")),
value.substring(value.indexOf("=")+1)));
}
//UrlEncodedFormEntity对自定义请求头(集合) 进行URL编码
try {
post.setEntity(new UrlEncodedFormEntity(list,HTTP.UTF_8));
//由HttpClient对象调用execute(),发送请求
//得到响应对象HttpResponse,由该对象获得服务响应信息
HttpResponse response = httpClient.execute(post);
//getEntity()
br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
//把获得响应信息显示到指定控件中
String readLine = null;
while((readLine = br.readLine()) != null){
allContent += readLine;
}
//发送消息
Message msg = new Message();
msg.obj = allContent;
msg.setTarget(handler);
msg.sendToTarget();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "";
}
/**
* 此方法用于发送GET请求
* @param String uri 表示服务程序
* @param String params 表示请求字符串
* @return String 返回响应信息
*/
public String getUserInforByGet(String uri , String params){
String allContent = "";
BufferedReader br = null;
//创建HttpClient对象
//创建一个HttpGet对象
HttpGet get = new HttpGet(uri);
/*
//设置请求参数
//存放请求参数对象的集合List
List list = new ArrayList();
//请求参数类型BasicNameValuePair
String[] nameVauePairs = params.split("&");
for(String value:nameVauePairs){
list.add(new BasicNameValuePair(value.substring(0, value.indexOf("=")),
value.substring(value.indexOf("=")+1)));
}
//UrlEncodedFormEntity对自定义请求头(集合) 进行URL编码
*/
try {
//String path = EntityUtils.toString(new UrlEncodedFormEntity(list, HTTP.UTF_8));
//get.setURI(new URI(get.getURI() + "?" + path));
get.setURI(new URI(get.getURI() + "?" + params));
//由HttpClient对象调用execute(),发送请求
//的到响应对象HttpResponse,由该对象获得服务响应信息
HttpResponse response = httpClient.execute(get);
//把获得响应信息显示到指定控件中
HttpEntity entity = response.getEntity();
br = new BufferedReader(new InputStreamReader(entity.getContent()));
String readLine = null;
while((readLine = br.readLine()) != null){
allContent += readLine;
}
//发送消息
Message msg = new Message();
msg.obj = allContent;
msg.setTarget(handler);
msg.sendToTarget();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(br != null){
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return "";
}
}