Apache HttpClient

Posted 鬼王呵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apache HttpClient相关的知识,希望对你有一定的参考价值。

1. HttpClientUtil 工具类[需要导入相关的包]


package com.until.hsx;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLHandshakeException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.ResponseHandler;
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.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;


/**
 * Apache HttpClient 4.5 工具类
 * @author huangsx
 *
 */
public class HttpClientUtil {

	/**
	 * UTF-8编码
	 */
	private static final String CHARSET_UTF8 = "UTF-8";
	/**
	 * GBK编码
	 */
	private static final String CHARSET_GBK = "GBK";
	/**
	 * 安全套接字层  ssl
	 */
	private static final String SSL_DEFAULT_SCHEME = "https";
	/**
	 * 安全套接字层  ssl的端口
	 */
	private static final int SSL_DEFAULT_PORT = 443;
	
	/**
	 * 异常自动恢复处理
	 */
	private static HttpRequestRetryHandler requestRetryHandler = new HttpRequestRetryHandler() {
		
		// 自定义恢复策略
		@SuppressWarnings("deprecation")
		@Override
		public boolean retryRequest(IOException exception, int exceptionCount, HttpContext context) {
			// 设置恢复策略,发生异常时自动重试3次
			if (exceptionCount >= 3) {
				return false;
			}
			if (exception instanceof NoHttpResponseException) {
				return true;
			}
			if (exception instanceof SSLHandshakeException) {
				return false;
			}
			HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
			boolean idempotent = (request instanceof HttpEntityEnclosingRequest);
			if (!idempotent) {
				return true;
			}
			return false;
		}
	};
	
	/**
	 * 使用ResponseHandler接口处理响应,HttpClient使用ResponseHandler自动管理连接的释放,实现连接的释放管理
	 */
	@SuppressWarnings("rawtypes")
	private static ResponseHandler responseHandler = new ResponseHandler() {

		@SuppressWarnings("deprecation")
		@Override
		public Object handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String charset = EntityUtils.getContentCharSet(entity) == null ? CHARSET_GBK : EntityUtils.getContentCharSet(entity);
				return new String(EntityUtils.toByteArray(entity), charset);
			}
			else {
				return null;
			}
		}
	};
	
	/**
	 * Get方式提交,url中包含参数
	 * @param url - 提交地址(格式:http://www.baidu.com?param1=one¶m2=two...)
	 * @return - 响应消息
	 */
	public static String get(String url) {
		return get(url, null, null);
	}
	
	/**
	 * Get方式提交,url中不包含参数
	 * @param url - 提交地址(格式:http://www.baidu.com/)
	 * @param params - 查询的参数集,Map键值对
	 * @return - 响应消息
	 */
	public static String get(String url, Map<String, String> params) {
		return get(url, params, null);
	}
	
	/**
	 * Get方式提交,url中不包含参数
	 * @param url - 提交地址(格式:http://www.baidu.com/)
	 * @param params - 查询的参数集,Map键值对
	 * @param charset - 查询的参数集的编码
	 * @return - 响应消息
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	public static String get(String url, Map<String, String> params, String charset) {
		if (url == null || url.length() <= 0) {
			return null;
		}
		List<NameValuePair> requestParams = getParamsList(params);
		if (requestParams != null && requestParams.size() > 0) {
			charset = (charset == null ? CHARSET_GBK : charset);
			String formatParams = URLEncodedUtils.format(requestParams, charset);
			url = (url.indexOf("?")) < 0 ? (url + "?" + formatParams) : (url.substring(0, url.indexOf("?") + 1) + formatParams);
		}
		DefaultHttpClient httpclient = getDefaultHttpClient(charset);
		HttpGet httpGet = new HttpGet(url);
		// 发送请求,得到响应
		String response = null;
		try {
			response = httpclient.execute(httpGet, responseHandler);
		} catch (ClientProtocolException e) {
			//TODO
			//throw new NetServiceException("客户端连接协议错误", e); 
			System.out.println("客户端连接协议错误");
			e.printStackTrace();
		} catch (IOException e) {
			//TODO
			//throw new NetServiceException("IO操作异常", e); 
			System.out.println("IO操作异常");
			e.printStackTrace();
		} finally {
			abortConnection(httpGet, httpclient);
		}
		System.out.println("response " + response);
		return response;
	}
	
	/**
	 * Post方式提交,URL中不包含提交参数
	 * @param url - 提交地址(格式:http://www.baidu.com/)
	 * @param params - 查询的参数集,Map键值对
	 * @return - 响应消息
	 */
	public static String post(String url, Map<String, String> params) {
		return post(url, params, null);
	}
	
	/**
	 * Post方式提交,URL中不包含提交参数
	 * @param url - 提交地址(格式:http://www.baidu.com/)
	 * @param params - 查询的参数集,Map键值对
	 * @param charset - 查询的参数集的编码
	 * @return - 响应消息
	 */
	@SuppressWarnings({ "deprecation", "unchecked" })
	public static String post(String url, Map<String, String> params, String charset) {
		if (url == null || url.length() <= 0) {
			return null;
		}
		// 创建HttpClinet实例
		DefaultHttpClient httpClient = getDefaultHttpClient(charset);
		UrlEncodedFormEntity formEntity = null;
		try {
			if (charset == null || charset.length() <= 0) {
 				formEntity = new UrlEncodedFormEntity(getParamsList(params));
			}
			else {
				formEntity = new UrlEncodedFormEntity(getParamsList(params), charset);
			}
		} catch (UnsupportedEncodingException e) {
			//TODO
			//throw new NetServiceException("不支持的编码集", e);
			System.out.println("不支持的编码集");
			e.printStackTrace();
		}
		HttpPost httpPost = new HttpPost(url);
		httpPost.setEntity(formEntity);
		// 发送请求,得到响应
		String response = null;
		try {
			response = httpClient.execute(httpPost, responseHandler);
		} catch (ClientProtocolException e) {
			//TODO
			//throw new NetServiceException("客户端连接协议错误", e);
			System.out.println("客户端连接协议错误");
			e.printStackTrace();
		} catch (IOException e) {
			//TODO
			//throw new NetServiceException("IO操作异常", e);
			System.out.println("IO操作异常");
			e.printStackTrace();
		} finally {
			abortConnection(httpPost, httpClient);
		}		
		System.out.println("response " + response);
		return response;
	}
	
	/**
	* Post方式提交,忽略URL中包含的参数,解决SSL双向数字证书认证
	* @param url - 提交地址
	* @param params - 提交参数集, 键/值对
	* @param charset - 参数编码集
	* @param keystoreUrl - 密钥存储库路径
	* @param keystorePassword - 密钥存储库访问密码
	* @param truststoreUrl - 信任存储库绝路径
	* @param truststorePassword - 信任存储库访问密码, 可为null
	* @return - 响应消息
	*/
	@SuppressWarnings({ "deprecation", "unchecked" })
	public static String post(String url, Map<String, String> params, String charset, final URL keystoreUrl, 
			final String keystorePassword, final URL truststoreUrl,	final String truststorePassword) {
		if (url == null || url.length()  <= 0) {
			return null;
		}
		DefaultHttpClient httpClient = getDefaultHttpClient(charset);
		UrlEncodedFormEntity formEntity = null;
		try {
			if (charset == null || charset.length() <= 0) {
				formEntity = new UrlEncodedFormEntity(getParamsList(params));
			} else {
				formEntity = new UrlEncodedFormEntity(getParamsList(params), charset);
			}
		} catch (UnsupportedEncodingException e) {
			//TODO
			//throw new NetServiceException("不支持的编码集", e);
			System.out.println("不支持的编码集");
			e.printStackTrace();
		}
		HttpPost hp = null;
		String response = null;
		try {
			KeyStore keyStore = createKeyStore(keystoreUrl, keystorePassword);
			KeyStore trustStore = createKeyStore(truststoreUrl, keystorePassword);
			SSLSocketFactory socketFactory = new SSLSocketFactory(keyStore,	keystorePassword, trustStore);
			Scheme scheme = new Scheme(SSL_DEFAULT_SCHEME, socketFactory, SSL_DEFAULT_PORT);
			httpClient.getConnectionManager().getSchemeRegistry().register(scheme);
			hp = new HttpPost(url);
			hp.setEntity(formEntity);
			response = httpClient.execute(hp, responseHandler);			
		} catch (NoSuchAlgorithmException e) {
			//TODO
			//throw new NetServiceException("指定的加密算法不可用", e);
			System.out.println("指定的加密算法不可用");
			e.printStackTrace();
		} catch (KeyStoreException e) {
			//TODO
			//throw new NetServiceException("keytore解析异常", e);
			System.out.println("keytore解析异常");
			e.printStackTrace();
		} catch (CertificateException e) {
			//TODO
			//throw new NetServiceException("信任证书过期或解析异常", e);
			System.out.println("信任证书过期或解析异常");
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			//TODO
			//throw new NetServiceException("keystore文件不存在", e);
			System.out.println("keystore文件不存在");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO
			//throw new NetServiceException("I/O操作失败或中断 ", e);
			System.out.println("I/O操作失败或中断");
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			//TODO
			//throw new NetServiceException("keystore中的密钥无法恢复异常", e);
			System.out.println("keystore中的密钥无法恢复异常");
			e.printStackTrace();
		} catch (KeyManagementException e) {
			//TODO
			//throw new NetServiceException("处理密钥管理的操作异常", e);
			System.out.println("处理密钥管理的操作异常");
			e.printStackTrace();
		} finally {
			abortConnection(hp, httpClient);
		}
		System.out.println("response " + response);
		return response;
	}
		
	/**
	 * 将传入的字符串参数转换为Map型
	 * @param paramsString - 传入的字符串型参数
	 * @return - 返回的Map型参数
	 */
	public static Map<String, String> paramsString2Map(String paramsString) {
		if (paramsString == null || paramsString.length() <= 0) {
			return null;
		}
		Map<String, String> paramsMap = new HashMap<String, String>();
		String[] paramsStringArray = paramsString.split("&");
		for (int index = 0; index < paramsStringArray.length; index++) {
			String nameValuePair = paramsStringArray[index];
			putParamsMapByNameValuePair(nameValuePair, paramsMap);
		}
		return paramsMap;
	}
	
	
	/**
	 * 把键值放入到Map中
	 * @param nameValuePair - 键值对(形式:name=value)
	 * @param paramsMap - 返回Map(形式:map<name, value>)
	 */
	private static void putParamsMapByNameValuePair(String nameValuePair, Map<String, String> paramsMap) {
		if (nameValuePair == null || nameValuePair.length() <= 0) {
			return;
		}
		int indexOf = nameValuePair.indexOf("=");
		if (indexOf != -1) {
			String key = nameValuePair.substring(0, indexOf);
			String value = nameValuePair.substring(indexOf + 1, nameValuePair.length());
			if (key != null && !"".equals(key)) {
				paramsMap.put(key, value);
			}
			else {
				paramsMap.put(key, "");
			}
		}
	}
	
	/**
	 * 将传入的键/值对参数转换为NameValuePair参数集
	 * @param paramsMap - 提交参数集, 键/值对
	 * @return - List<NameValuePair>
	 */
	//TODO
	private static List<NameValuePair> getParamsList(Map<String, String> paramsMap) {
		if (paramsMap == null || paramsMap.size() <= 0) {
			return null;
		}
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		for (Map.Entry<String, String> map : paramsMap.entrySet()) {
			params.add(new BasicNameValuePair(map.getKey(), map.getValue()));
		}
		return params;
	}
	
	/**
	 * 获取DefaultHttpClient实例
	 * @param charset - 字符编码
	 * @return - DefaultHttpClient实例
	 */
	//TODO
	@SuppressWarnings("deprecation")
	private static DefaultHttpClient getDefaultHttpClient(final String charset) {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		httpClient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
		//模拟浏览器,解决一些服务器程序只允许浏览器访问的问题
		httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)");
		httpClient.getParams().setParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, Boolean.FALSE);
		httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, charset == null ? CHARSET_GBK : charset);
		httpClient.setHttpRequestRetryHandler(requestRetryHandler);
		return httpClient;
	}
	
	/**
	 * 释放HttpClient连接
	 * @param hrb - HttpRequestBase
	 * @param httpClient - httpClient
	 */
	//TODO
	@SuppressWarnings("deprecation")
	private static void abortConnection(final HttpRequestBase hrb, final HttpClient httpClient){
		if (hrb != null) {
			hrb.abort();
		}
		if (httpClient != null) {
			httpClient.getConnectionManager().shutdown();
		}
	}
	
	/**
	 * 从给定的路径中加载此 KeyStore
	 * @param url - URL地址
	 * @param password
	 * @return
	 * @throws KeyStoreException
	 * @throws NoSuchAlgorithmException
	 * @throws CertificateException
	 * @throws IOException
	 */
	//TODO
	private static KeyStore createKeyStore(final URL url, final String password)
			throws KeyStoreException, NoSuchAlgorithmException,	CertificateException, IOException {
		if (url == null) {
			throw new IllegalArgumentException("Keystore url may not be null");
		}
		KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
		InputStream is = null;
		try {
			is = url.openStream();
			keyStore.load(is, password != null ? password.toCharArray() : null);
		} finally {
			if (is != null){
				is.close();
				is = null;
			}
		}
		return keyStore;
	}
	
}

/**
 * 自定义的异常处理类NetServiceException
 * @author huangsx
 *
 */
/*class NetServiceException extends Exception {
	
	public NetServiceException() {
		
	}
	
	public NetServiceException(String message) {
		super(message);
	}
	
	public NetServiceException(String message, Exception e) {
		super(message, e);
	}
}*/

2. HttpClientUtilTest 测试类

package test.hsx;

import java.util.Map;

import org.junit.Test;

import com.until.hsx.HttpClientUtil;

public class HttpClientUtilTest {
	
	@Test
	public void postRegDepartmentsWsgGetDepartmentList() throws Exception {
		// http://192.168.100.116:8080/CloudUser/ws/rest/dept/getlist   @FormParam("jsonParams") String jsonParams
		//String paramsString = "jsonParams={\"Name\": \"Test\" }";
		// hosId=15813&depId=1344&depCode=4451&bookable=1
		String paramsString = "jsonParams=\"{\"hosId\":\"15813\", \"depId\":\"1344\", \"depCode\":\"4511\", \"bookable\":\"1\"}\"";
		Map<String, String> map = HttpClientUtil.paramsString2Map(paramsString);
		System.out.println("map " + map);
		String result = HttpClientUtil.post("http://localhost:8080/CloudUser/ws/rest/dept/getlist", map);
		System.out.println("result \n" + result);
	}
	
	@Test
	public void postRegDepartmentsWsgGetDepartmentDesc() throws Exception{
		// http://192.168.100.116:8080/CloudUser/ws/rest/dept/getdesc  @FormParam("id") int id
		String paramsString = "id=1344";
		Map<String, String> map = HttpClientUtil.paramsString2Map(paramsString);
		System.out.println("map " + map);
		String result = HttpClientUtil.post("http://localhost:8080/CloudUser/ws/rest/dept/getdesc", map);
		System.out.println("result \n" + result);
	}
	
	@Test
	public void getDoctorFans() throws Exception {
		// http://192.168.100.116:8080/CloudUser/ws/rest/doctor/fans   @FormParam("doctorId") String doctorId
		String paramsString = "doctorId=745";
		Map<String, String> map = HttpClientUtil.paramsString2Map(paramsString);
		System.out.println("map " + map);
		String result = HttpClientUtil.get("http://localhost:8080/CloudUser/ws/rest/doctor/fans", map);
		System.out.println("result \n" + result);
	}
	
	@Test
	public void getExamWsGetCheckInfoTest() throws Exception {
		// http://192.168.100.116:8080/CloudUser/ws/rest/checkInfo/13555  @PathParam("patId") Integer patId
		String paramsString = "patId=13555";
		Map<String, String> map = HttpClientUtil.paramsString2Map(paramsString);
		System.out.println("map " + map);
		String result = HttpClientUtil.get("http://localhost:8080/CloudUser/ws/rest/checkInfo/13555");
		System.out.println("result\n" + result);
	}
	
	@Test
	public void getDoctorWsGetDoctorCountTest() throws Exception {
		// http://192.168.100.116:8080/CloudUser/ws/rest/doctor/count  @FormParam("hosId")Integer hosId
		String paramsString = "hosId=15812";
		Map<String, String> map = HttpClientUtil.paramsString2Map(paramsString);
		System.out.println("map " + map);
		String result = HttpClientUtil.get("http://localhost:8080/CloudUser/ws/rest/doctor/count", map);
		System.out.println("result \n" + result);
	}
	
}


3. 注意事项:在测试的时候一定要将参数设置正确,尤其是jsonParams中的参数类型问题。

4. 待完善: 尝试自己写个抛异常的类


以上是关于Apache HttpClient的主要内容,如果未能解决你的问题,请参考以下文章

Apache HttpClient Android (Gradle)

使用Mockito模拟Apache HTTPClient

Java通过代码发给手机发信息

请问有org.apache.commons.httpclient.HttpClient.*的jar是哪个?该去哪儿下载

Apache HttpClient之fluent API的使用

如何接收httpclient发送的请求