HttpClient 详解
备注:
01. 网络请求为耗时操作,需要在子线程进行处理;
02. 网络请求必须在清单文件中配置 internet 权限;
1.应用场景
web站点中有某些页面,不是通过一个简单的url就可以访问的,可能需要用户登录且具有相应的权限才可以访问的,这就需要涉及Session、Cookie的处理
为了更好的处理Web站点的请求,包括处理Session、Cookie等细节问题,就需要使用Apache下的HttpClient。
(HttpURLConnection也可以处理上述问题,但操作起来难度大。比较复杂)
2.安装包及发展情形
- 在org.apache包下,Android已经成功地集成了HttpClient,开发人员可以直接使用
- 在高版本中,HttpClient 需要导包使用,使用频率降低。eg,在4.0 版本可以直接使用,而在6.0版本需要导包使用(包名:org.apache.http.legacy.jar)。
3.方式
请求方式常用的有 get 和 post 请求,post 请求的时候需要传递参数。
4.步骤
4.1 get 请求
- 创建httpClient 对象
- HttpClient hc=new DefaultHttpClient();
- 获取请求方式 get 请求
- HttpGet hg=new HttpGet(path); path为传入的路径
- 发送请求
- HttpResponse hr = hc.execute(hg); hg 为传入的请求方式
- 获取响应码信息
- int num= hr.getStatusLine().getStatusCode();
- 判断 如果响应码为 200,则表示 连接成功
- if(num==200){}
- 连接成功后,获取实体内容
- HttpEntity result = response.getEntity();
- 对实体内容进行处理,常见三种方式
- 方式1 转换成String
- String str=EntityUtils.toString(result);
- 方式2 转换成byte[]
- byte[] byteArray = EntityUtils.toByteArray(result);
- 方式3 得到输入流
- InputStream content = result.getContent();
- 方式1 转换成String
4.2 post 请求
- 创建httpClient 对象
- HttpClient hc=new DefaultHttpClient();
- 获取请求方式 post请求
- HttpPost hp=new HttpPost(path); path为传入的路径
- 设置要传入的参数信息
- HttpEntity entity=null;
- 存放所有要传入的参数信息
- List < BasicNameValuePair > parameters=new ArrayList< BasicNameValuePair>();
- BasicNameValuePair是存储键值对的类
- parameters.add(new BasicNameValuePair(“key”, “6e5e1292af5ebfd8eff8f2392187f5bd”));
- List < BasicNameValuePair > parameters=new ArrayList< BasicNameValuePair>();
- entity=new UrlEncodedFormEntity(parameters, “utf-8”); 设置发送的参数及其编码
- hp.setEntity(entity); 设置参数信息
- 发送(执行)请求
- HttpResponse response=hc.execute(hp); hp 为传入的请求方式
- 获取响应码信息 先获取响应行,通过响应行获取响应码信息
- int num= response.getStatusLine().getStatusCode();
- 判断 如果响应码为 200,则表示 连接成功
- if(num==200){}
- 连接成功后,获取实体内容
- HttpEntity result = response.getEntity();
- 对实体内容进行处理,常见三种方式
- 方式1 转换成String
- String str=EntityUtils.toString(result);
- 方式2 转换成byte[]
- byte[] byteArray = EntityUtils.toByteArray(result);
- 方式3 得到输入流
- InputStream content = result.getContent();
- 方式1 转换成String
5. 其他方法
- 如果需要发送请求参数,则可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数
- 对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数
- 调用HttpClient对象的execute()方法发送请求,执行该方法返回一个HttpResponse。
- 调用HttpResponse的getAllHeader()、getHeaders(String name)等方法可获取服务器的响应头;
- 调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容;程序可通过该对象获取服务器的响应内容。
5.1 HttpClient-GET方式
- //得到HttpClient 对象
HttpClient httpClient = new DefaultHttpClient(); - //使用get方式访问网络并指定路径
HttpGet httpGet = new HttpGet(url); - //执行联网操作,发送get请求
HttpResponse httpResponse = httpClient.execute(httpGet); - //获取状态行
response.getStatusLine(); - //获取状态码(200)
int statusCode = line.getStatusCode(); - //获取实体对象,实体指的是服务器返回的数据
HttpEntity entity = response.getEntity(); - //将服务器返回的实体转出字符串
EntityUtils.toString(entity, “utf-8”);
5.2 HttpClient-POST方式
- //创建httpClient对象
HttpClient client = new DefaultHttpClient(); - //创建http post请求对象,并指定路径
HttpPost post = new HttpPost(url); // 将要提交的数据以name–value的形式传递
BasicNameValuePair pair = new BasicNameValuePair(“name”, name);//把要提交的数据以实体的形式设置到post对象中
List parameters = new ArrayList();
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(parameters, “utf-8”);
post.setEntity(entity);//执行联网操作,进行post请求
HttpResponse response = client.execute(post);//获取状态行
StatusLine line = response.getStatusLine();//获取状态码(200)
int statusCode = line.getStatusCode();//获取实体对象,实体指的是服务器返回的数据
HttpEntity entity = response.getEntity();//将服务器返回的实体转出字符串
EntityUtils.toString(entity, “utf-8”);
6.案例
6.1 get 请求
6.1.0 导包 因为编译版本为 6.0 ,需要导包
6.1.1 布局文件
`<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:onClick="requestDataByGet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HttpClient请求数据GET" />
</RelativeLayout>`
6.1.2 主要代码
`public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//设置点击事件Get
public void requestDataByGet (View v){
new Thread(){
public void run() {
//调用Get方法
getHttpClient();
};
}.start();
}
public void getHttpClient(){
String path="http://apis.juhe.cn/catering/query?key=4ca0d9cf9012b72e817917560b38e0d2&lng=121.538123&lat=31.677132&radius=2000";
//1. 创建httpClient 对象
HttpClient hc=new DefaultHttpClient();
//2. 获取请求方式
HttpGet hg=new HttpGet(path);
try {
//3. 发送请求
HttpResponse hr = hc.execute(hg);
//4. 获取响应信息
//判断 如果响应码为200的时候
if(hr.getStatusLine().getStatusCode()==200){
HttpEntity entity = hr.getEntity();
//打印 entity 字符串
String string = EntityUtils.toString(entity);
Log.d("AAAA", "Entity:"+string);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}`
6.1.3 清单文件配置 internet 权限
` <uses-permission android:name="android.permission.INTERNET"/>`
6.1.2 post请求
6.1.2.0 导包
6.1.2.1 布局文件
`<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:onClick="requestDataByPost"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HttpClientByPost请求" />
</RelativeLayout>`
6.1.2.2 主要代码
`public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void requestDataByPost(View v){
new Thread(){
public void run() {
postHttpClient();
};
}.start();
}
protected void postHttpClient() {
String path="http://v.juhe.cn/postcode/search";
// String path="http://v.juhe.cn/postcode/pcd";
String value="6e5e1292af5ebfd8eff8f2392187f5bd";
String address="木渎";
//1. 获取 HttpClient 对象
HttpClient hc=new DefaultHttpClient();
//2.获取 post 对象
HttpPost hp=new HttpPost(path);
HttpEntity entity=null;
try {
//存放所有要存放的信息
List<BasicNameValuePair> parameters=new ArrayList<BasicNameValuePair>();
parameters.add(new BasicNameValuePair("key", value));
parameters.add(new BasicNameValuePair("pid","15"));
parameters.add(new BasicNameValuePair("cid", "205"));
parameters.add(new BasicNameValuePair("did", "2125"));
parameters.add(new BasicNameValuePair("q", address));
entity=new UrlEncodedFormEntity(parameters, "utf-8");
//3. 设置要传入的参数
hp.setEntity(entity);
//4. 发送请求
HttpResponse hr = hc.execute(hp);
//5 接受响应
//判断
if(hr.getStatusLine().getStatusCode()==200){
HttpEntity result = hr.getEntity();
// Log.d("aaaa","HttpEntity未转:"+result.toString());//不能直接tostring,这样为引用地址
String re = EntityUtils.toString(result);
Log.d("aaaa","HttpEntity:"+re);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
`
6.1.2.3 清单文件配置 internet 权限
` <uses-permission android:name="android.permission.INTERNET"/>`
7.特性
- 基于标准、纯净的java语言。实现了Http1.0和Http1.1
- 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)
- 支持HTTPS协议。
- 通过Http代理建立透明的连接。
利用CONNECT方法通过Http代理建立隧道的https连接。
Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
插件式的自定义认证方案。
便携可靠的套接字工厂使它更容易的使用第三方解决方案。
连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
自动处理Set-Cookie中的Cookie。
插件式的自定义Cookie策略。
Request的输出流可以避免流中内容直接缓冲到socket服务器。
Response的输入流可以有效的从socket服务器直接读取相应内容。
在http1.0和http1.1中利用KeepAlive保持持久连接。
直接获取服务器发送的response code和 headers。
设置连接超时的能力。
实验性的支持http1.1 response caching。
源代码基于Apache License 可免费获取。
8.扩充
8.1 URL的定义与组成
URL(Uniform Resource Locator) 统一资源定位符,它是指向互联网”资源”的指针
URL的组成部分:http://www.mbalib.com/china/index.htm
其中
* http://:代表一个万维网服务器
* mbalib.com/:服务器的域名,或服务器名称
* china/:子目录,类似于文件夹
* index.htm:是文件夹中的一个文件
* /chia/index.htm统称为url的路径