最近对应用中的一处代码进行优化,把之前是单线程串行执行的一系列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