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); } } }