HttpClient 实战

  最近,开发了一个RESTFul方式Web Service的跨应用调用。本人采用了Apache 的HttpClient客户端组件。
  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);

猜你喜欢

转载自hailong-qin.iteye.com/blog/2020959