欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

HttpClient实例

程序员文章站 2022-07-10 16:18:36
...
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.http.Consts;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
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.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
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.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

public class HttpClient {

	private static final Logger logger = LoggerFactory.getLogger(HttpClient.class);

	public static String utf8 = "utf-8";
	
	private static String userAgentName = "User-Agent";
	private static String userAgentValue = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) "
			+ "Gecko/20100101 Firefox/45.0";

	private String userAgent = null;
	
	public void setUserAgent(String userAgent) {
		this.userAgent = userAgent;
	}

	private static TrustManager manager = new X509TrustManager() {

		@Override
		public X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub

		}
	};

	private static PoolingHttpClientConnectionManager connectionManager = null;

	// 路由(MAX_PER_ROUTE)是对最大连接数(MAX_TOTAL)的细分,整个连接池的限制数量实际使用DefaultMaxPerRoute并非MaxTotal。
	// 设置过小无法支持大并发(ConnectionPoolTimeoutException: Timeout waiting for
	// connection from pool)
	static {

		try {
			SSLContext context = SSLContext.getInstance("TLS");
			context.init(null, new TrustManager[] { manager }, null);
			SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(context,
					NoopHostnameVerifier.INSTANCE);
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
					.<ConnectionSocketFactory>create()
					.register("http", PlainConnectionSocketFactory.INSTANCE)
					.register("https", socketFactory)
					.build();
			connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			connectionManager.setMaxTotal(50);// 将最大连接数增加到50
			connectionManager.setDefaultMaxPerRoute(5);// 设置路由最大连接数
		} catch (NoSuchAlgorithmException e) {
			logger.error(e.getMessage());
		} catch (KeyManagementException e) {
			logger.error(e.getMessage());
		}

	}
	CloseableHttpClient httpsClient = null;

	private void create() {
		RequestConfig defaultRequestConfig = RequestConfig.custom()
				.setCookieSpec(CookieSpecs.STANDARD_STRICT)
				.setExpectContinueEnabled(true)
				.setConnectionRequestTimeout(5000)
				.setConnectTimeout(10000)
				.setSocketTimeout(10000)
				.setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST))
				.setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC)).build();
		HttpRequestRetryHandler httpRequestRetryHandler = (exception, executionCount, context) -> {
			if (executionCount >= 3) {// 如果已经重试了5次,就放弃                     
                return false;
            }  
            if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试                    
                return true;
            }  
            if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常                   
                return false;
            }                 
            if (exception instanceof InterruptedIOException) {// 超时                   
                return false;
            }  
            if (exception instanceof UnknownHostException) {// 目标服务器不可达                   
                return false;
            }  
            if (exception instanceof ConnectTimeoutException) {// 连接被拒绝                   
                return false;
            }  
            if (exception instanceof SSLException) {// ssl握手异常                    
                return false;
            }  
              
            HttpClientContext clientContext = HttpClientContext.adapt(context);
            HttpRequest request = clientContext.getRequest();
            // 如果请求是幂等的,就再次尝试  
            if (!(request instanceof HttpEntityEnclosingRequest)) {
                return true;
            }  
            return false;
		};
		httpsClient = HttpClients.custom()
				.setConnectionManager(connectionManager)
				.setDefaultRequestConfig(defaultRequestConfig)
				.setRetryHandler(httpRequestRetryHandler)
				.build();

	}
	
	public void close() {
		try {
			if(httpsClient != null) {
				httpsClient.close();
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
		}
	}

	private HttpClient() {
		create();
	}

	public static HttpClient createHttpsClient() {
		return new HttpClient();
	}

	private Result toResult(CloseableHttpResponse response) throws IOException {
		Result result = null;
		try {
			String body = EntityUtils.toString(response.getEntity(), HttpClient.utf8);
			result = new Result();
			result.setBody(body);
			result.setStatus(response.getStatusLine().getStatusCode());
			if (logger.isDebugEnabled()) {
				logger.debug("https result: {}", result);
			}
		} finally {
			if (response != null) {
				response.close();
			}
		}
		return result;
	}

	/**
	 * post 不带参数请求, CloseableHttpResponse 需要调用方关闭
	 * 
	 * @param url
	 * @return
	 * @throws IOException
	 */
	public CloseableHttpResponse doHttpsPost(String url) throws IOException {
		return doHttpsPost(url, (List<NameValuePair>) null);
	}

	/**
	 * post 不带参数请求
	 * 
	 * @param url
	 * @return Result 返回带字符串响应结果和响应状态的对象
	 * @throws IOException
	 */
	public Result doHttpsPostReturnResult(String url) throws IOException {
		return toResult(doHttpsPost(url));
	}

	/**
	 * post 不带参数,返回对象,响应结果必须是json 对象
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> T doHttpsPostReturnObject(String url, Class<T> c) throws IOException {
		T result = null;
		Result response = doHttpsPostReturnResult(url);
		result = JSON.parseObject(response.getBody(), c);
		return result;
	}

	/**
	 * 不带参数,返回集合,响应结果必须是json 数组
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> List<T> doHttpsPostReturnArray(String url, Class<T> c) throws IOException {
		List<T> result = null;
		Result response = doHttpsPostReturnResult(url);
		result = JSON.parseArray(response.getBody(), c);
		return result;
	}

	public CloseableHttpResponse doHttpsPost(String url, Map<String, Object> params) 
			throws IOException {
		List<NameValuePair> values = new ArrayList<>();
		if (params != null) {
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				NameValuePair p = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
				values.add(p);
			}
		}
		return doHttpsPost(url, values);
	}

	/**
	 * post 任意键值对数据
	 * 
	 * @param url
	 * @return Result 返回带字符串响应结果和响应状态的对象
	 * @throws IOException
	 */
	public Result doHttpsPostReturnResult(String url, Map<String, Object> params) throws IOException {
		return toResult(doHttpsPost(url, params));
	}

	/**
	 * post 任意键值对数据,返回对象,响应结果必须是json 对象
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> T doHttpsPostReturnObject(String url, Map<String, Object> params, Class<T> c) 
			throws IOException {
		T result = null;
		Result response = doHttpsPostReturnResult(url, params);
		result = JSON.parseObject(response.getBody(), c);
		return result;
	}

	/**
	 * post 键值对数据,返回集合,响应结果必须是json 数组
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> List<T> doHttpsPostReturnArray(String url, Map<String, Object> params, Class<T> c) 
			throws IOException {
		List<T> result = null;
		Result response = doHttpsPostReturnResult(url, params);
		result = JSON.parseArray(response.getBody(), c);
		return result;
	}

	public CloseableHttpResponse doHttpsPost(String url, List<NameValuePair> values) throws IOException {
		HttpPost post = new HttpPost(url);
		if (values != null) {
			UrlEncodedFormEntity entity = new UrlEncodedFormEntity(values, Consts.UTF_8);
			post.setEntity(entity);
		}
		RequestConfig requestConf = RequestConfig.custom()
				.setSocketTimeout(10000)
				.setConnectTimeout(10000)
				.build();
		post.setConfig(requestConf);
		setCommonHeader(post);
		CloseableHttpResponse response = httpsClient.execute(post);
		return response;
	}

	/**
	 * post NameValuePair键值对参数
	 * 
	 * @param url
	 * @return Result 返回带字符串响应结果和响应状态的对象
	 * @throws IOException
	 */
	public Result doHttpsPostReturnResult(String url, List<NameValuePair> values) throws IOException {
		return toResult(doHttpsPost(url, values));
	}

	/**
	 * post NameValuePair键值对参数
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> T doHttpsPostReturnObject(String url, List<NameValuePair> values, Class<T> c) 
			throws IOException {
		T result = null;
		Result response = doHttpsPostReturnResult(url, values);
		result = JSON.parseObject(response.getBody(), c);
		return result;
	}

	/**
	 * post NameValuePair键值对参数
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> List<T> doHttpsPostReturnArray(String url, List<NameValuePair> values, Class<T> c) 
			throws IOException {
		List<T> result = null;
		Result response = doHttpsPostReturnResult(url, values);
		result = JSON.parseArray(response.getBody(), c);
		return result;
	}

	public CloseableHttpResponse doHttpsPost(String url, String values) throws IOException {
		HttpPost post = new HttpPost(url);
		if (values != null) {
			StringEntity entity = new StringEntity(values, Consts.UTF_8);
			post.setEntity(entity);
		}
		setCommonHeader(post);
		CloseableHttpResponse response = httpsClient.execute(post);
		return response;
	}

	/**
	 * post 任何字符串数据,包括json等
	 * 
	 * @param url
	 * @return Result 返回带字符串响应结果和响应状态的对象
	 * @throws IOException
	 */
	public Result doHttpsPostReturnResult(String url, String values) throws IOException {
		return toResult(doHttpsPost(url, values));
	}

	/**
	 * post 任何字符串数据,包括json等,返回对象,响应结果必须是json 对象
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> T doHttpsPostReturnObject(String url, String values, Class<T> c) throws IOException {
		T result = null;
		Result response = doHttpsPostReturnResult(url, values);
		result = JSON.parseObject(response.getBody(), c);
		return result;
	}

	/**
	 * post 任何字符串数据,包括json等,响应结果必须是json 数组
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> List<T> doHttpsPostReturnArray(String url, String values, Class<T> c) throws IOException {
		List<T> result = null;
		Result response = doHttpsPostReturnResult(url, values);
		result = JSON.parseArray(response.getBody(), c);
		return result;
	}

	public CloseableHttpResponse doHttpsGet(String url) throws IOException {
		HttpGet get = new HttpGet(url);
		RequestConfig requestConf = RequestConfig.custom()
				.setSocketTimeout(10000)
				.setConnectTimeout(10000)
				.build();
		get.setConfig(requestConf);
		setCommonHeader(get);
		CloseableHttpResponse response = httpsClient.execute(get);
		return response;
	}

	/**
	 * post 不带参数请求
	 * 
	 * @param url
	 * @return Result 返回带字符串响应结果和响应状态的对象
	 * @throws IOException
	 */
	public Result doHttpsGetReturnResult(String url) throws IOException{
		return toResult(doHttpsGet(url));
	}

	/**
	 * post 不带参数,返回对象,响应结果必须是json 对象
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> T doHttpsGetReturnObject(String url, Class<T> c) throws IOException {
		T result = null;
		Result response = doHttpsGetReturnResult(url);
		result = JSON.parseObject(response.getBody(), c);
		return result;
	}

	/**
	 * 不带参数,返回集合,响应结果必须是json 数组
	 * 
	 * @param url
	 * @param c
	 * @return
	 * @throws IOException
	 */
	public <T> List<T> doHttpsGetReturnArray(String url, Class<T> c) throws IOException {
		List<T> result = null;
		Result response = doHttpsGetReturnResult(url);
		result = JSON.parseArray(response.getBody(), c);
		return result;
	}

	private void setCommonHeader(HttpRequestBase request) {
		if(userAgent == null) {
			request.setHeader(userAgentName, userAgentValue);
		} else {
			request.setHeader(userAgentName, userAgent);
		}
		
	}
	
	public static class Result {
		private String body;
		private Integer status;

		public String getBody() {
			return body;
		}

		public void setBody(String body) {
			this.body = body;
		}

		public Integer getStatus() {
			return status;
		}

		public void setStatus(Integer status) {
			this.status = status;
		}

		@Override
		public String toString() {
			return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
		}

	}
	
}
相关标签: json java