我们在访问网路时,有时候会用到Android已经封装好的一个类——HttpClient,这个类就相当于一个小型的浏览器,集成了很多允许我们访问网络的方法,在普通的应用程序中,我们只需封装HttpRequest对象并传给HttpClient,使用HttpClient就可以访问网络了。如果请求的端口或者URL没有变化,可以采用单例模式来封装一个HttpClient。
代码片段,双击复制
public static synchronized HttpClient getHttpClient() {
if (httpClient == null ) {
HttpParams params = new BasicHttpParams();
// 设置一些基本参数
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, encoding);
HttpProtocolParams.setUseExpectContinue(params, true );
HttpProtocolParams
.setUserAgent(
params,
"Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
+ "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1" );
// 超时设置
ConnManagerParams.setTimeout(params, 1000);
HttpConnectionParams.setConnectionTimeout(params, 2000);
HttpConnectionParams.setSoTimeout(params, 4000 );
// 设置HttpClient支持HTTP和HTTPS两种模式
SchemeRegistry schReg = new SchemeRegistry();
schReg.register( new Scheme( "http" , PlainSocketFactory
.getSocketFactory(), 80 ));
schReg.register( new Scheme( "https" , SSLSocketFactory
.getSocketFactory(), 443 ));
// 使用线程安全的连接管理来创建HttpClient
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(
params, schReg);
httpClient = new DefaultHttpClient(conMgr, params);
}
return httpClient;
}
在需要调用的地方调用上面的方法,获得httpClient实例:
代码片段,双击复制
public static byte [] httpConnect(HttpRequest request) throws Exception {
HttpResponse response = null ;
if (request instanceof HttpGet) {
HttpGet get = (HttpGet) request;
response = getHttpClient().execute(get);
} else if (request instanceof HttpPost) {
HttpPost post = (HttpPost) request;
response = getHttpClient().execute(post);
}
if (response != null
&& response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity resEntity = response.getEntity();
return (resEntity == null ) ? null : EntityUtils
.toByteArray(resEntity);
}
return null ;
}
这样就可以连接网络了。
但有些时候,情况会有些复杂,某些程序需要访问不同的端口,如果用单例模式,就需要手动的清除这个单例,在需要的地方再重新实例化,这样会造成程序上的混乱,而我们不用单例模式的话,每次访问网络是都一个新的httpClient对象,又会造成每次的session值不一致,服务器会认为你的多次请求并非在一次会话中,从而出现问题,打个比方:程序第一次请求服务器是进行登录功能,请求成功,服务器返回给response一个sessionid用作本次会话的标示,然而再下一次访问的时候,因为我们不用单例模式了,httpClient会重新实例化一个对象,这次请求的时候如果在request对象中没有sessionid的设置,那么服务器会认为这次请求和上次的请求不在一个会话中,造成错误。
我木有找到如何有效的在单例模式中关闭httpClient的方法,所以我的解决办法是手动的将每次的request请求保持一致
代码片段,双击复制
private static synchronized HttpClient getHttpClient(HttpRequest request) {
HttpParams params = new BasicHttpParams();
// 设置一些基本参数
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(params, true );
HttpProtocolParams
.setUserAgent(
params,
"Mozilla/5.0(Linux;U;Android 2.2.1;en-us;Nexus One Build.FRG83) "
+ "AppleWebKit/553.1(KHTML,like Gecko) Version/4.0 Mobile Safari/533.1" );
// 超时设置
ConnManagerParams.setTimeout(params, 1000 * 8);
HttpConnectionParams.setConnectionTimeout(params, 1000 * 10);
HttpConnectionParams.setSoTimeout(params, 1000 * 10 );
// 设置HttpClient支持HTTP和HTTPS两种模式
SchemeRegistry schReg = new SchemeRegistry();
schReg.register( new Scheme( "http" , PlainSocketFactory
.getSocketFactory(), getHttpPort(request)));
schReg.register( new Scheme( "https" ,
SSLSocketFactory.getSocketFactory(), getHttpPort(request)));
// 使用线程安全的连接管理来创建HttpClient
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(
params, schReg);
return new DefaultHttpClient(conMgr, params);
}
之后在调用处:
代码片段,双击复制
private static byte [] httpConnect(HttpRequest request) throws Exception {
// Log.e("请求", CommonDefines.SESSIONID);
HttpResponse response = null ;
if (CommonDefines.SESSIONID != null ||CommonDefines.SESSIONID!= "" ) {
//设置sessionid,把第一次请求的id放在之后要请求的request报文头里
request.setHeader( "Cookie" , CommonDefines.SESSIONID);
}
if (request instanceof HttpGet) {
HttpGet get = (HttpGet) request;
response = getHttpClient(request).execute(get);
} else if (request instanceof HttpPost) {
HttpPost post = (HttpPost) request;
response = getHttpClient(request).execute(post);
}
if (response != null
&& response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity resEntity = response.getEntity();
Header[] headers = response.getHeaders( "set-cookie" );
//保存服务器返回的session
for ( int i = 0 ; i < headers.length; i++) {
// Log.e("sessionid", headers.getValue());
String value = headers.getValue();
CommonDefines.SESSIONID = value
.substring( 0 , value.indexOf( ";" ));
}
return (resEntity == null ) ? null : EntityUtils
.toByteArray(resEntity);
}
return null ;
}
OK,这样就解决了在httpClient中保持session一致的问题了。
本人才疏学浅,如果有大神发现这个代码有问题,欢迎回帖,如果有有效的清除httpClient对象的方法,希望大神们也回复下哦