HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。Commons-httpclient项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。
HttpClient工具类HttpClientUtil代码:
package com.credit56.ws.common; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.InterruptedIOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.net.ssl.SSLHandshakeException; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.StatusLine; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.config.RequestConfig; 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.client.protocol.HttpClientContext; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HttpContext; /** * * <p class="detail"> * 功能:Http Client 工具类 * </p> * * @ClassName: HttpClientUtil * @version V1.0 * @date 2014-1-27 * @author qinhailong */ public class HttpClientUtil { private static int connectionTimeOut = 30000; private static int socketTimeOut = 60000; private static String DEFAULT_CHARSET = "utf-8"; private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeOut) .setConnectTimeout(connectionTimeOut).build(); // 自定义响应处理 private static ResponseHandler<String> responseStringHandler = new ResponseHandler<String>() { public synchronized String handleResponse(HttpResponse response) throws ClientProtocolException, IOException { String responseBody = ""; StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode >= 300) { throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase()); } if (HttpStatus.SC_OK == statusCode) { HttpEntity entity = response.getEntity(); if (null == entity) { throw new ClientProtocolException("Response contains no content"); } else { responseBody = getResponseBody(entity); } } return responseBody; } }; // 自定义响应处理 private static ResponseHandler<HttpResponse> responseHandler = new ResponseHandler<HttpResponse>() { public synchronized HttpResponse handleResponse(HttpResponse response) throws ClientProtocolException, IOException { HttpEntity entity = response.getEntity(); if (null == entity) { throw new ClientProtocolException("Response contains no content"); } else { StringEntity stringEntity = new StringEntity(getResponseBody(entity), DEFAULT_CHARSET); response.setEntity(stringEntity); } return response; } }; /** * * <p class="detail"> * 功能:新建HttpClient * </p> * * @author qinhailong * @date Jan 27, 2014 */ public static HttpClient getNewHttpClient() { try { PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(); cm.setMaxTotal(100); HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 3) { // 如果超过最大重试次数,那么就不要继续了 return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof ConnectTimeoutException) { // Connection refused return false; } if (exception instanceof NoHttpResponseException) { // 如果服务器丢掉了连接,那么就重试 return true; } if (exception instanceof SSLHandshakeException) { // 不要重试SSL握手异常 return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { return true; } return false; } }; CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm) .setRetryHandler(myRetryHandler).build(); return httpClient; } catch (Exception e) { e.printStackTrace(); } return null; } /** * * <p class="detail"> * 功能:Http GET 方法 返回类型为String * </p> * * @author qinhailong * @date 2014-2-13 * @param url * 请求URL * @return String * @throws HttpException * @throws IOException */ public static String get(String url) throws HttpException, IOException { HttpClient httpClient = getNewHttpClient(); HttpGet getMethod = getMethod(url); String responseBody = ""; try { responseBody = httpClient.execute(getMethod, responseStringHandler); } finally { getMethod.releaseConnection(); } return responseBody; } /** * * <p class="detail"> * 功能:Http GET 方法 返回类型为HttpResponse * </p> * * @author qinhailong * @date 2014-2-13 * @param url * 请求URL * @return HttpResponse * @throws HttpException * @throws IOException */ public static HttpResponse sendGetRequest(String url) throws HttpException, IOException { HttpClient httpClient = getNewHttpClient(); HttpGet getMethod = getMethod(url); HttpResponse httpResponse = null; try { httpResponse = httpClient.execute(getMethod, responseHandler); } finally { getMethod.releaseConnection(); } return httpResponse; } /** * <p class="detail"> * 功能:POST请求 返回响应体 String 内容 * </p> * * @author qinhailong * @date 2014年1月27日 * @param url * 请求地址 * @param postData * 请求参数 * @return String * @throws HttpException */ public static String post(String url, Map<String, String> postData) throws Exception { if (null == postData || postData.isEmpty()) { return get(url); } HttpPost postMethod = null; String responseBody = ""; try { HttpClient httpClient = getNewHttpClient(); postMethod = postMethod(url); Set<Entry<String, String>> entrySet = postData.entrySet(); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); Iterator<Entry<String, String>> it = entrySet.iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next(); formparams.add(new BasicNameValuePair(entry.getKey().toString(), entry.getValue().toString())); } UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, DEFAULT_CHARSET); postMethod.setEntity(entity); responseBody = httpClient.execute(postMethod, responseStringHandler); } catch (Exception e) { throw e; } finally { postMethod.releaseConnection(); } return responseBody; } /** * * <p class="detail"> * 功能:POST请求 返回响应信息 * </p> * * @author qinhailong * @date 2014-2-13 * @param url * @param postData * 请求地址 * @return 请求参数 * @throws Exception */ public static HttpResponse sendPostRequest(String url, Map<String, String> postData) throws Exception { if (null == postData || postData.isEmpty()) { return sendGetRequest(url); } HttpPost postMethod = null; HttpResponse httpResponse = null; try { HttpClient httpClient = getNewHttpClient(); postMethod = postMethod(url); Set<Entry<String, String>> entrySet = postData.entrySet(); List<NameValuePair> formparams = new ArrayList<NameValuePair>(); Iterator<Entry<String, String>> it = entrySet.iterator(); while (it.hasNext()) { Map.Entry<String, String> entry = (Map.Entry<String, String>) it.next(); formparams.add(new BasicNameValuePair(entry.getKey().toString(), entry.getValue().toString())); } if (null != formparams && formparams.size() > 0) { UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, DEFAULT_CHARSET); postMethod.setEntity(entity); } httpResponse = httpClient.execute(postMethod, responseHandler); } catch (Exception e) { throw e; } finally { postMethod.releaseConnection(); } return httpResponse; } /** * * <p class="detail"> * 功能:得到GET METHOD * </p> * * @author qinhailong * @date 2014-2-12 * @param url * 请求URL * @return */ public static HttpGet getMethod(String url) { HttpGet getMethod = new HttpGet(url); getMethod.setConfig(requestConfig); getMethod.setHeaders(getHeaders()); return getMethod; } /** * * <p class="detail"> * 功能:得到POST METHOD * </p> * * @author qinhailong * @date 2014-2-12 * @param url * 请求URL * @return */ public static HttpPost postMethod(String url) { HttpPost postMethod = new HttpPost(url); postMethod.setConfig(requestConfig); postMethod.setHeaders(getHeaders()); return postMethod; } /** * * <p class="detail"> * 功能:请求头信息 * </p> * * @author qinhailong * @date Jan 27, 2014 */ private static Header[] getHeaders() { ArrayList<Header> headers = new ArrayList<Header>(); headers.add(new BasicHeader("Accept", "text/html, text/json, text/xml, html/text, */*")); headers.add(new BasicHeader("Accept-Language", "zh-cn,en-us,zh-tw,en-gb,en;")); headers.add(new BasicHeader("Accept-Charset", "gbk,gb2312,utf-8,BIG5,ISO-8859-1;")); headers.add(new BasicHeader("Connection", "keep-alive")); headers.add(new BasicHeader("Cache-Control", "no-cache")); headers.add(new BasicHeader("Accept-Encoding", "gzip")); headers.add(new BasicHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; CIBA)")); return headers.toArray(new Header[0]); } /** * * <p class="detail"> * 功能:从响应体内容 * </p> * * @author qinhailong * @date 2014-2-12 * @param httpResponse * httpClient 响应 * @return 响应体内容 * @throws IOException * @throws IllegalStateException */ public static String getResponseBody(HttpEntity entity) throws IllegalStateException, IOException { StringBuffer respnseBody = new StringBuffer(); BufferedReader in = null; try { InputStream is = entity.getContent(); in = new BufferedReader(new InputStreamReader(is, DEFAULT_CHARSET)); String line = null; while (null != (line = in.readLine())) { respnseBody.append(line); } } catch (IllegalStateException e1) { throw e1; } catch (IOException e2) { throw e2; } finally { in.close(); } return respnseBody.toString(); } /** * * <p class="detail"> * 功能:从响应中得到响应体内容 * </p> * * @author qinhailong * @date 2014-2-12 * @param httpResponse * httpClient 响应 * @return 响应体内容 * @throws IOException * @throws IllegalStateException */ public static String getResponseBody(HttpResponse httpResponse) throws IllegalStateException, IOException { String respnseBody = ""; if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = httpResponse.getEntity(); if (null != entity) { respnseBody = getResponseBody(entity); } } return respnseBody; } }
由于响应体内容过大,是按块传送的,所以要用ResponseHandler回调的方式处理响应体内容,这样httpclient 会自己处理socket连接,不然的话,数据还没有读取完全,而socket又关闭了,会抛出socket关闭异常。
// 自定义响应处理 private static ResponseHandler<HttpResponse> responseHandler = new ResponseHandler<HttpResponse>() { public synchronized HttpResponse handleResponse(HttpResponse response) throws ClientProtocolException, IOException { HttpEntity entity = response.getEntity(); if (null == entity) { throw new ClientProtocolException("Response contains no content"); } else { StringEntity stringEntity = new StringEntity(getResponseBody(entity), DEFAULT_CHARSET); response.setEntity(stringEntity); } return response; } };
httpClient.execute(postMethod, responseHandler);