(点击
上方公众号
,可快速关注)
来源:刘望舒
链接:blog.csdn.net/itachi85/article/details/51010109
前言
上一篇我们了解了HTTP协议原理,这一篇我们来讲讲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
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.HttpU
RLConnection
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
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