最近对应用中的一处代码进行优化,把之前是单线程串行执行的一系列http请求改成了多线程并发执行以提高效率。结果程序刚开始运行的时候比较正常,到后面http请求多了之后就抛出异常了,异常栈信息如下:
01-07 11:45:45.576: W/System.err(4727): org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:176)
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
01-07 11:45:45.586: W/System.err(4727): org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
01-07 11:45:45.586: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
01-07 11:45:45.596: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:176)
01-07 11:45:45.596: W/System.err(4727): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:326)
01-07 11:45:45.596: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-07 11:45:45.596: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-07 11:45:45.596: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-07 11:45:45.596: W/System.err(4727): at com.yulore.yellowpage.http.NetUtil.post(NetUtil.java:92)
01-07 11:45:45.596: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.recognize(ResolveTask.java:123)
01-07 11:45:45.596: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:43)
01-07 11:45:45.596: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:1)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:176)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:326)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-07 11:45:45.606: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-07 11:45:45.606: W/System.err(4727): at com.yulore.yellowpage.http.NetUtil.post(NetUtil.java:92)
01-07 11:45:45.606: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.recognize(ResolveTask.java:123)
01-07 11:45:45.606: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:43)
01-07 11:45:45.606: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:1)
01-07 11:45:45.606: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.616: W/System.err(4727): org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:176)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:326)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-07 11:45:45.616: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-07 11:45:45.616: W/System.err(4727): at com.yulore.yellowpage.http.NetUtil.post(NetUtil.java:92)
01-07 11:45:45.616: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.recognize(ResolveTask.java:123)
01-07 11:45:45.616: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:43)
01-07 11:45:45.616: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:1)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.616: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.626: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-07 11:45:45.626: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-07 11:45:45.626: W/System.err(4727): at java.lang.Thread.run(Thread.java:856)
01-07 11:45:45.626: W/System.err(4727): org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:326)
01-07 11:45:45.626: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
01-07 11:45:45.636: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
01-07 11:45:45.636: W/System.err(4727): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
01-07 11:45:45.636: W/System.err(4727): at com.yulore.yellowpage.http.NetUtil.post(NetUtil.java:92)
01-07 11:45:45.636: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.recognize(ResolveTask.java:123)
01-07 11:45:45.636: W/System.err(4727): at at at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:43)
01-07 11:45:45.636: W/System.err(4727): at com.yulore.yellowpage.business.ResolveTask.call(ResolveTask.java:1)
01-07 11:45:45.636: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-07 11:45:45.646: W/System.err(4727): at java.lang.Thread.run(Thread.java:856)
01-07 11:45:45.646: W/System.err(4727): java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-07 11:45:45.646: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-07 11:45:45.646: W/System.err(4727): at java.lang.Thread.run(Thread.java:856)
01-07 11:45:45.656: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-07 11:45:45.656: W/System.err(4727): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-07 11:45:45.656: W/System.err(4727): at java.lang.Thread.run(Thread.java:856)
org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection,英语好的人一眼就能看出来,ConnectionPool请求超时了,为什么会出现这样的错误了?
原因:http连接池中的连接个数是一定,每次执行http请求后,如果连接没有被释放,会导致http连接池中的数目越来越少,直到最后没有可用http连接。
解决办法:每次请求成功或者请求失败,都手动的去释放连接资源。
先把出错的代码贴出来,如下:
package com.yulore.yellowpage.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import com.yulore.yellowpage.util.LogUtil;
/**
*
* @author Mathew
*
*/
public class NetUtil {
private static HttpClient customerHttpClient;
private static final String CHARSET_UTF8 = HTTP.UTF_8;
private static final String TAG = NetUtil.class.getSimpleName();
/**
* post 请求
*
* @param vo
* @return
* @throws JSONException
*/
public static Object post(RequestVo vo) throws JSONException,
ClientProtocolException, SocketTimeoutException, IOException {
HttpClient client = getNewHttpClient(vo.context);
LogUtil.e(TAG, "post URL:" + vo.requestUrl);
HttpPost post = new HttpPost(vo.requestUrl);
HttpParams params = new BasicHttpParams();//
if(vo.timeout!=0){
HttpConnectionParams.setConnectionTimeout(params, vo.timeout); // 连接超时
HttpConnectionParams.setSoTimeout(params, vo.timeout); // 响应超时
}
post.setParams(params);
post.setHeader("Accept-Encoding", "gzip");
Object obj = null;
if (vo.requestDataMap != null) {
HashMap<String, String> map = vo.requestDataMap;
ArrayList<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
for (Map.Entry<String, String> entry : map.entrySet()) {
BasicNameValuePair pair = new BasicNameValuePair(
entry.getKey(), entry.getValue());
pairList.add(pair);
}
HttpEntity entity = new UrlEncodedFormEntity(pairList, "UTF-8");
post.setEntity(entity);
}
HttpResponse response = client.execute(post);// 包含响应的状态和返回的结果==
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in post");
in = new GZIPInputStream(in);
}
String result = getHTMLContent(in);
// String result = EntityUtils.toString(response.getEntity(), "UTF-8");
LogUtil.w(TAG, result);// 打印得到的JSON字符串
if (vo.callback != null) {
JSONObject json = new JSONObject(result);
String status = json.getString("status");
if ("0".equals(status)) {
LogUtil.i(TAG, "缓存Json串");
vo.callback.process(result);
}
}
obj = vo.jsonParser.parseJSON(result);// 回调类真正起作用的地方
return obj;
}
return null;
}
/**
*
* @param vo
* @return
* @throws JSONException
* @throws IOException
* @throws ClientProtocolException
* @throws SocketTimeoutException
*/
public static Object get(RequestVo vo) throws JSONException,
ClientProtocolException, IOException,SocketTimeoutException {
HttpClient client = getNewHttpClient(vo.context);
LogUtil.e(TAG, "get URL:" + vo.requestUrl);
// 需要对特殊字符进行转义
HttpGet get = new HttpGet(vo.requestUrl);
HttpParams params = new BasicHttpParams();//
if(vo.timeout!=0){
HttpConnectionParams.setConnectionTimeout(params, vo.timeout); // 连接超时
HttpConnectionParams.setSoTimeout(params, vo.timeout); // 响应超时
}
get.setParams(params);
get.setHeader("Accept-Encoding", "gzip");
Object obj = null;
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in get");
in = new GZIPInputStream(in);
}
String result = getHTMLContent(in);
// String result = EntityUtils.toString(response.getEntity(), "UTF-8");
LogUtil.w(TAG, result);// 打印得到的JSON字符串
if (vo.callback != null) {
JSONObject json = new JSONObject(result);
String status = json.getString("status");
if ("0".equals(status)) {
LogUtil.i(TAG, "缓存Json串");
vo.callback.process(result);
}
}
obj = vo.jsonParser.parseJSON(result);
}
return obj;
}
private static String getHTMLContent(InputStream in) {
StringBuffer sb = new StringBuffer();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(in,"utf-8"));
String line = null;
while((line=br.readLine())!=null){
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
*
* @param vo
* @return
* @throws JSONException
* @throws IOException
* @throws ClientProtocolException
* @throws SocketTimeoutException
*/
public static String requestGet(Context context,String url) throws JSONException,
ClientProtocolException, IOException,SocketTimeoutException {
HttpClient client = getNewHttpClient(context);
LogUtil.e(TAG, "requestGet URL:" + url);
// 需要对特殊字符进行转义
HttpGet get = new HttpGet(url);
HttpParams params = new BasicHttpParams();//
get.setParams(params);
get.setHeader("Accept-Encoding", "gzip");
String result = null;
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in requestGet");
in = new GZIPInputStream(in);
}
result = getHTMLContent(in);
LogUtil.w(TAG, result);// 打印得到的JSON字符串
}
return result;
}
public interface ResponseStrCallback {
public void process(String responseStr);
}
private static synchronized HttpClient getNewHttpClient(Context context) {
if (null == customerHttpClient) {
HttpParams params = new BasicHttpParams();
// 设置一些基本参数
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, CHARSET_UTF8);
// 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, 8000);
/* 连接超时 */
int ConnectionTimeOut = 10000;
if (!isWifiDataEnable(context)) {
ConnectionTimeOut = 15000;
}
HttpConnectionParams
.setConnectionTimeout(params, ConnectionTimeOut);
/* 请求超时 */
HttpConnectionParams.setSoTimeout(params, ConnectionTimeOut);
// 设置我们的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);
customerHttpClient = new DefaultHttpClient(conMgr, params);
}
return customerHttpClient;
}
/**
* 判断wifi 是否可用
*
* @param context
* @return
* @throws Exception
*/
public static boolean isWifiDataEnable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isWifiDataEnable = false;
isWifiDataEnable = connectivityManager.getNetworkInfo(
ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
return isWifiDataEnable;
}
/**
* 获得网络连接是否可用
*
* @param context
* @return
*/
public static boolean hasNetwork(Context context) {
ConnectivityManager con = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo workinfo = con.getActiveNetworkInfo();
if (workinfo == null || !workinfo.isAvailable()) {
// Toast.makeText(context, R.string.network_not_available,
// Toast.LENGTH_SHORT)
// .show();
return false;
}
return true;
}
}
我改动了两个地方:
(1) getNewHttpClient方法增加以下代码:
// 超时设置 从连接池中取连接的超时时间
ConnManagerParams.setTimeout(params, 20000);
// 设置最大连接数
ConnManagerParams.setMaxTotalConnections(params, 200);
// 设置每个路由最大连接数
ConnPerRouteBean connPerRoute = new ConnPerRouteBean(20);
ConnManagerParams.setMaxConnectionsPerRoute(params,connPerRoute);
(2) 在get/post方法中处理InputStream完了之后,关闭InputStream
public static Object get(RequestVo vo) throws JSONException,
ClientProtocolException, IOException,SocketTimeoutException {
HttpClient client = getNewHttpClient(vo.context);
LogUtil.e(TAG, "get URL:" + vo.requestUrl);
// 需要对特殊字符进行转义
HttpGet get = new HttpGet(vo.requestUrl);
HttpParams params = new BasicHttpParams();//
if(vo.timeout!=0){
HttpConnectionParams.setConnectionTimeout(params, vo.timeout); // 连接超时
HttpConnectionParams.setSoTimeout(params, vo.timeout); // 响应超时
}
get.setParams(params);
get.setHeader("Accept-Encoding", "gzip");
Object obj = null;
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = null;
try{
in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in get");
in = new GZIPInputStream(in);
}
String result = getHTMLContent(in);
// String result = EntityUtils.toString(response.getEntity(), "UTF-8");
LogUtil.d(TAG, result);// 打印得到的JSON字符串
if (vo.callback != null) {
JSONObject json = new JSONObject(result);
String status = json.getString("status");
if ("0".equals(status)) {
LogUtil.i(TAG, "缓存Json串");
vo.callback.process(result);
}
}
obj = vo.jsonParser.parseJSON(result);
}finally{
if(in!=null){
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return obj;
}
将 in.close()放在finally中,这样每次都会关闭InputStream了。
最后贴上完整的代码:
package com.yulore.yellowpage.http;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnPerRouteBean;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import com.yulore.yellowpage.util.LogUtil;
/**
* 封装http请求的工具类
*/
public class NetUtil {
private static HttpClient customerHttpClient;
private static final String CHARSET_UTF8 = HTTP.UTF_8;
private static final String TAG = NetUtil.class.getSimpleName();
/**
* post 请求
*
* @param vo
* @return
* @throws JSONException
*/
public static Object post(RequestVo vo) throws JSONException,
ClientProtocolException, SocketTimeoutException, ConnectTimeoutException,IOException {
HttpClient client = getNewHttpClient(vo.context);
LogUtil.e(TAG, "post URL:" + vo.requestUrl);
HttpPost post = new HttpPost(vo.requestUrl);
HttpParams params = new BasicHttpParams();//
if(vo.timeout!=0){
HttpConnectionParams.setConnectionTimeout(params, vo.timeout); // 连接超时
HttpConnectionParams.setSoTimeout(params, vo.timeout); // 响应超时
}
post.setParams(params);
post.setHeader("Accept-Encoding", "gzip");
if (vo.requestDataMap != null) {
HashMap<String, String> map = vo.requestDataMap;
ArrayList<BasicNameValuePair> pairList = new ArrayList<BasicNameValuePair>();
for (Map.Entry<String, String> entry : map.entrySet()) {
BasicNameValuePair pair = new BasicNameValuePair(
entry.getKey(), entry.getValue());
pairList.add(pair);
}
HttpEntity entity = new UrlEncodedFormEntity(pairList, "UTF-8");
post.setEntity(entity);
}
HttpResponse response = client.execute(post);// 包含响应的状态和返回的结果==
Object obj = null;
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = null;
try{
in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in post");
in = new GZIPInputStream(in);
}
String result = getHTMLContent(in);
// String result = EntityUtils.toString(response.getEntity(), "UTF-8");
LogUtil.d(TAG, result);// 打印得到的JSON字符串
if (vo.callback != null) {
JSONObject json = new JSONObject(result);
String status = json.getString("status");
if ("0".equals(status)) {
LogUtil.i(TAG, "缓存Json串");
vo.callback.process(result);
}
}
obj = vo.jsonParser.parseJSON(result);// 回调类真正起作用的地方
}finally{
if(in!=null){
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return obj;
}
/**
*
* @param vo
* @return
* @throws JSONException
* @throws IOException
* @throws ClientProtocolException
* @throws SocketTimeoutException
*/
public static Object get(RequestVo vo) throws JSONException,
ClientProtocolException, IOException,SocketTimeoutException {
HttpClient client = getNewHttpClient(vo.context);
LogUtil.e(TAG, "get URL:" + vo.requestUrl);
// 需要对特殊字符进行转义
HttpGet get = new HttpGet(vo.requestUrl);
HttpParams params = new BasicHttpParams();//
if(vo.timeout!=0){
HttpConnectionParams.setConnectionTimeout(params, vo.timeout); // 连接超时
HttpConnectionParams.setSoTimeout(params, vo.timeout); // 响应超时
}
get.setParams(params);
get.setHeader("Accept-Encoding", "gzip");
Object obj = null;
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = null;
try{
in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in get");
in = new GZIPInputStream(in);
}
String result = getHTMLContent(in);
// String result = EntityUtils.toString(response.getEntity(), "UTF-8");
LogUtil.d(TAG, result);// 打印得到的JSON字符串
if (vo.callback != null) {
JSONObject json = new JSONObject(result);
String status = json.getString("status");
if ("0".equals(status)) {
LogUtil.i(TAG, "缓存Json串");
vo.callback.process(result);
}
}
obj = vo.jsonParser.parseJSON(result);
}finally{
if(in!=null){
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return obj;
}
private static String getHTMLContent(InputStream in) {
StringBuffer sb = new StringBuffer();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(in,"utf-8"));
String line = null;
while((line=br.readLine())!=null){
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(br!=null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
/**
*
* @param vo
* @return
* @throws JSONException
* @throws IOException
* @throws ClientProtocolException
* @throws SocketTimeoutException
*/
public static String requestGet(Context context,String url) throws JSONException,
ClientProtocolException, IOException,SocketTimeoutException {
HttpClient client = getNewHttpClient(context);
LogUtil.e(TAG, "requestGet URL:" + url);
// 需要对特殊字符进行转义
HttpGet get = new HttpGet(url);
HttpParams params = new BasicHttpParams();//
get.setParams(params);
get.setHeader("Accept-Encoding", "gzip");
String result = null;
HttpResponse response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
InputStream in = null;
try{
in = response.getEntity().getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
LogUtil.e(TAG, "gzip InputStream in requestGet");
in = new GZIPInputStream(in);
}
result = getHTMLContent(in);
LogUtil.d(TAG, result);// 打印得到的JSON字符串
}finally{
if(in!=null){
try {
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return result;
}
public interface ResponseStrCallback {
public void process(String responseStr);
}
private static synchronized HttpClient getNewHttpClient(Context context) {
if (null == customerHttpClient) {
HttpParams params = new BasicHttpParams();
// 设置一些基本参数
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, CHARSET_UTF8);
// 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, 20000);
// 设置最大连接数
ConnManagerParams.setMaxTotalConnections(params, 200);
// 设置每个路由最大连接数
ConnPerRouteBean connPerRoute = new ConnPerRouteBean(20);
ConnManagerParams.setMaxConnectionsPerRoute(params,connPerRoute);
/* 连接超时 */
int ConnectionTimeOut = 10000;
if (!isWifiDataEnable(context)) {
ConnectionTimeOut = 15000;
}
HttpConnectionParams
.setConnectionTimeout(params, ConnectionTimeOut);
/* 请求超时 */
HttpConnectionParams.setSoTimeout(params, ConnectionTimeOut);
// 设置我们的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);
customerHttpClient = new DefaultHttpClient(conMgr, params);
}
return customerHttpClient;
}
/**
* 判断wifi 是否可用
*
* @param context
* @return
* @throws Exception
*/
public static boolean isWifiDataEnable(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
boolean isWifiDataEnable = false;
isWifiDataEnable = connectivityManager.getNetworkInfo(
ConnectivityManager.TYPE_WIFI).isConnectedOrConnecting();
return isWifiDataEnable;
}
/**
* 获得网络连接是否可用
*
* @param context
* @return
*/
public static boolean hasNetwork(Context context) {
if(context==null){
LogUtil.e(TAG, "context is null");
return false;
}
ConnectivityManager con = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo workinfo = con.getActiveNetworkInfo();
if (workinfo == null || !workinfo.isAvailable()) {
// Toast.makeText(context, R.string.network_not_available,
// Toast.LENGTH_SHORT)
// .show();
return false;
}
return true;
}
}
关于HttpClient的使用,可用去HttpClient官网查看,HttpClient 3.x 和HttpClient 4.x的使用还是有一些区别的
HttpClient官网:http://hc.apache.org/
HttpClient 4.3 Tutorial:http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/index.html