本文展示基于apache httpComponents实现的REST客户端,可以作为RestTemplate底层的实现支撑。
1、基于HttpClient 4.5 +
2、仅实现同步调用。
3、通用客户端,仅支持Rest调用,即请求和响应均为文本类型。
类列表:
1、HttpClientConfiguration:客户端的主要配置,包括连接超时、连接池大小等。
2、HttpClientTemplate:接口,描述了客户端支持的基本操作。
3、AbstractHttpClientTemplate:2、接口的基本实现,主要用于构建默认参数和方法。
4、HttpComponentsClientTemplate:主要实现类,用户描述GET/POST操作的过程。
5、HttpComponentsClientBuilder:静态类,用于外部便捷的构建client,可以被spring、springboot集成(自动装配时使用)。
一、HttpClientConfiguration
/** * HTTP Client配置管理 **/ public class HttpClientConfiguration implements Serializable { //目前不能修改,常量值 private static final int DEFAULT_MAX_CONNECTIONS = 1024; //连接创建 public static final long DEFAULT_CONNECTION_TIMEOUT = 500; //SO_TIMEOUT public static final long DEFAULT_SOCKET_TIMEOUT = 500; //连接池中的连接被保活的时长 public static final long DEFAULT_KEEP_ALIVE_TIME = 6000; //请求异常(exception),重试的次数,默认为0,不重试 public static final int DEFAULT_HTTP_RETRY_TIMES = 0; //是否重试 public static final boolean DEFAULT_HTTP_RETRY_ON_FAILURE = false; public static final int DEFAULT_CONNECTION_REQUEST_TIMEOUT = 1500; public static final String HTTP_CLIENT_TYPE_OK_HTTP = "okHttp"; public static final String HTTP_CLIENT_TYPE_HTTP_COMPONENTS = "httpComponents"; //连接创建 private long connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; //SO_TIMEOUT private long socketTimeout = DEFAULT_SOCKET_TIMEOUT; //连接池中的连接被保活的时长 private long keepAliveTime = DEFAULT_KEEP_ALIVE_TIME; //请求异常(exception),重试的次数,默认为0,不重试 private int retryTimes = DEFAULT_HTTP_RETRY_TIMES; //是否重试 private boolean retryOnFailure = DEFAULT_HTTP_RETRY_ON_FAILURE; private String charset = ContextConstants.DEFAULT_CHARSET; //全局headers,即所有请求都会添加 private Map<String, String> globalHeaders; private int connectionRequestTimeout = 1500; private String clientType = HTTP_CLIENT_TYPE_HTTP_COMPONENTS; public void setConnectionTimeout(Long connectionTimeout) { this.connectionTimeout = connectionTimeout; } public void setSocketTimeout(Long socketTimeout) { this.socketTimeout = socketTimeout; } public void setKeepAliveTime(Long keepAliveTime) { this.keepAliveTime = keepAliveTime; } public void setRetryTimes(Integer retryTimes) { this.retryTimes = retryTimes; } public void setRetryOnFailure(Boolean retryOnFailure) { this.retryOnFailure = retryOnFailure; } public void setCharset(String charset) { this.charset = charset; } public Long getConnectionTimeout() { return connectionTimeout; } public Long getSocketTimeout() { return socketTimeout; } public Long getKeepAliveTime() { return keepAliveTime; } public Integer getRetryTimes() { return retryTimes; } public Boolean getRetryOnFailure() { return retryOnFailure; } public String getCharset() { return charset; } public Map<String, String> getGlobalHeaders() { return globalHeaders; } public void setGlobalHeaders(Map<String, String> globalHeaders) { this.globalHeaders = globalHeaders; } public int getMaxConnections() { return DEFAULT_MAX_CONNECTIONS; } public int getConnectionRequestTimeout() { return connectionRequestTimeout; } public void setConnectionRequestTimeout(int connectionRequestTimeout) { this.connectionRequestTimeout = connectionRequestTimeout; } public String getClientType() { return clientType; } public void setClientType(String clientType) { this.clientType = clientType; } private HttpClientConfiguration() { } /** * 构建一个常规配置 * * @param globalHeaders * @return */ public static HttpClientConfiguration common(Map<String, String> globalHeaders) { HttpClientConfiguration configuration = new HttpClientConfiguration(); configuration.setCharset(ContextConstants.DEFAULT_CHARSET);//UTF-8 configuration.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);//500 configuration.setSocketTimeout(DEFAULT_SOCKET_TIMEOUT);//500 configuration.setKeepAliveTime(DEFAULT_KEEP_ALIVE_TIME);//6000 configuration.setRetryOnFailure(DEFAULT_HTTP_RETRY_ON_FAILURE);//FALSE configuration.setRetryTimes(DEFAULT_HTTP_RETRY_TIMES);//0 if (globalHeaders != null) { configuration.setGlobalHeaders(globalHeaders); } configuration.setConnectionRequestTimeout(DEFAULT_CONNECTION_REQUEST_TIMEOUT); return configuration; } public static HttpClientConfiguration common() { return common(null); } }
1)connectionTimeout、socketTimeout,我们约定为500ms,对于普通WEB接口而言,此参数为权衡值,你可以根据自己的业务现状适度调整。
2)keepAliveTime:连接池中的连接被保活的时长,默认为6000ms,不建议设置太大。
3)retryOnFailure:当请求调用失败时,是否支持重试,失败主要为IO异常,强烈建议此值为false。
4)retryTimes:当retryOnFailure=true时,失败重试的次数,建议为0。
5)连接池容量,此处为1024,大家一定要合理修改此值。默认值太小,容易导致问题。
二、HttpClientTemplate
public interface HttpClientTemplate extends BeanLifeCycle { /** * 普通get操作 * * @param uri 不应该包含查询字符串 * @return */ public String get(String uri); /** * @param uri 不包含查询字符串 * @param parameters 查询字符串,编码之前原始字符串,内部会提供编码和转义。默认UTF-8 * @return */ public String get(String uri, Map<String, String> parameters); /** * @param uri 不应该包含查询字符串 * @param parameters 查询字符串,编码之前的原始字符串 * @param headers http header * @return */ public String get(String uri, Map<String, String> parameters, Map<String, String> headers); /** * 普通post * * @param uri 不应该包含查询字符串 * @return */ public String post(String uri); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON内容文本,应该使用与client相同的编码进行 * @return */ public String post(String uri, String content); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON格式文本 * @param parameters 查询字符串 * @return */ public String post(String uri, String content, Map<String, String> parameters); /** * 数据将通过body发送 * * @param uri 不应该包含查询字符串 * @param content JSON格式文本,body * @param parameters 查询字符串 * @param headers headers * @return */ public String post(String uri, String content, Map<String, String> parameters, Map<String, String> headers); /** * 返回底层的httpClient,通常情况是用户希望直接使用此client做自定义操作。 * * @return */ public Object getClient(); public String clientType(); }
三、AbstractHttpClientTemplate
public abstract class AbstractHttpClientTemplate implements HttpClientTemplate { //全局headers,即所有请求都会添加,可以被用户指定的headers覆盖 protected Map<String, String> globalHeaders; protected static final String CONTENT_TYPE_JSON = "application/json";//default //json格式,限定 protected static final String CONTENT_TYPE_JSON_PATTERN = CONTENT_TYPE_JSON + "; charset={0}";//default protected HttpClientConfiguration configuration = HttpClientConfiguration.common(); protected String charset = configuration.getCharset(); private volatile boolean init = false; public AbstractHttpClientTemplate() { } public AbstractHttpClientTemplate(HttpClientConfiguration configuration) { if (configuration != null) { this.configuration = configuration; this.globalHeaders = configuration.getGlobalHeaders(); } } public void setGlobalHeaders(Map<String, String> globalHeaders) { this.globalHeaders = globalHeaders; configuration.setGlobalHeaders(globalHeaders); } public synchronized void init() { if (init) { return; } init = true; } protected HttpClientConfiguration configuration() { return this.configuration; } }
四、HttpComponentsClientTemplate实现类
import org.apache.commons.lang3.StringUtils; import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.RequestBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.io.IOException; import java.nio.charset.Charset; import java.text.MessageFormat; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 基于HttpComponents实现的客户端,只支持String类型请求,即REST **/ public class HttpComponentsClientTemplate extends AbstractHttpClientTemplate { private CloseableHttpClient httpClient; private volatile boolean init = false; private List<HttpRequestInterceptor> requestInterceptors; private List<HttpResponseInterceptor> responseInterceptors; public void setRequestInterceptors(List<HttpRequestInterceptor> requestInterceptors) { this.requestInterceptors = requestInterceptors; } public void setResponseInterceptors(List<HttpResponseInterceptor> responseInterceptors) { this.responseInterceptors = responseInterceptors; } public HttpComponentsClientTemplate() { super(); } public HttpComponentsClientTemplate(HttpClientConfiguration configuration) { super(configuration); } @Override public synchronized void init() { if (init) { return; } super.init(); httpClient = HttpComponentsClientBuilder.build(configuration(), requestInterceptors, responseInterceptors); init = true; } private void parameters(RequestBuilder requestBuilder, Map<String, String> parameters) { if (parameters == null || parameters.isEmpty()) { return; } for (Map.Entry<String, String> entry : parameters.entrySet()) { String value = entry.getValue() == null ? "" : entry.getValue(); requestBuilder.addParameters(new BasicNameValuePair(entry.getKey(), value)); } } private void headers(RequestBuilder requestBuilder, Map<String, String> headers) { if (headers == null && globalHeaders == null) { return; } Map<String, String> _headers = new HashMap<>(); if (globalHeaders != null && !globalHeaders.isEmpty()) { _headers.putAll(globalHeaders); } if (headers != null && !headers.isEmpty()) { _headers.putAll(headers); } for (Map.Entry<String, String> entry : _headers.entrySet()) { String value = entry.getValue() == null ? "" : entry.getValue(); requestBuilder.addHeader(entry.getKey(), value); } } @Override public String get(String uri) { return get(uri, null); } @Override public String get(String uri, Map<String, String> parameters) { return get(uri, parameters, null); } @Override public String get(String uri, Map<String, String> parameters, Map<String, String> headers) { if (StringUtils.isBlank(uri)) { return null; } try { RequestBuilder requestBuilder = RequestBuilder.get(uri); parameters(requestBuilder, parameters); //对于get请求,增补一个常规header String contentType = MessageFormat.format(CONTENT_TYPE_JSON_PATTERN, charset); requestBuilder.addHeader(HttpHeaders.CONTENT_TYPE, contentType); //用户自定义header(可以覆盖增补的header) headers(requestBuilder, headers); requestBuilder.setCharset(Charset.forName(charset)); HttpUriRequest request = requestBuilder.build(); return process(request); } catch (Exception e) { throw new RuntimeException(e); } } @Override public String post(String uri) { return post(uri, null, null); } @Override public String post(String uri, String content) { return post(uri, content, null); } @Override public String post(String uri, String content, Map<String, String> parameters) { return post(uri, content, parameters, null); } @Override public String post(String uri, String content, Map<String, String> parameters, Map<String, String> headers) { if (StringUtils.isBlank(uri)) { return null; } try { RequestBuilder requestBuilder = RequestBuilder.post(uri); parameters(requestBuilder, parameters); requestBuilder.setCharset(Charset.forName(charset)); if (content != null) { StringEntity stringEntity = new StringEntity(content, ContentType.create(CONTENT_TYPE_JSON, charset)); requestBuilder.setEntity(stringEntity); } else { String contentType = MessageFormat.format(CONTENT_TYPE_JSON_PATTERN, charset); requestBuilder.addHeader(HttpHeaders.CONTENT_TYPE, contentType); } headers(requestBuilder, headers); HttpUriRequest request = requestBuilder.build(); return process(request); } catch (Exception e) { throw new RuntimeException(e); } } private String process(HttpUriRequest request) throws Exception { CloseableHttpResponse response = null; try { response = httpClient.execute(request); StatusLine statusLine = response.getStatusLine(); int statusCode = statusLine.getStatusCode(); if (statusCode != 200) { request.abort(); throw new RuntimeException("HttpClient error, status=" + statusCode + ",message:" + statusLine.getReasonPhrase()); } HttpEntity entity = response.getEntity(); String result = null; if (entity != null) { result = EntityUtils.toString(entity, charset); } EntityUtils.consume(entity); return result; } finally { if (response != null) { response.close(); } } } @Override public void close() throws IOException { if (httpClient != null) { httpClient.close(); } } @Override public HttpClient getClient() { return httpClient; } @Override public String clientType() { return HttpClientConfiguration.HTTP_CLIENT_TYPE_HTTP_COMPONENTS; } }
五、HttpComonentsClientBuilder构建类
import org.apache.http.HttpRequestInterceptor; import org.apache.http.HttpResponseInterceptor; import org.apache.http.client.config.RequestConfig; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClientBuilder; import java.util.List; import java.util.concurrent.TimeUnit; public final class HttpComponentsClientBuilder { /** * used HttpClient * * @return */ public static CloseableHttpClient build(HttpClientConfiguration configuration) { return build(configuration, null, null); } public static CloseableHttpClient build(HttpClientConfiguration configuration, List<HttpRequestInterceptor> requestInterceptors, List<HttpResponseInterceptor> responseInterceptors) { HttpClientBuilder builder = HttpClientBuilder.create(); DefaultHttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(configuration.getRetryTimes(), configuration.getRetryOnFailure()); builder.setRetryHandler(retryHandler); builder.setConnectionTimeToLive(configuration.getKeepAliveTime(), TimeUnit.MILLISECONDS); if (requestInterceptors != null) { for (HttpRequestInterceptor interceptor : requestInterceptors) { builder.addInterceptorLast(interceptor); } } if (responseInterceptors != null) { for (HttpResponseInterceptor interceptor : responseInterceptors) { builder.addInterceptorLast(interceptor); } } //connectionRequestTimeout: //连接池模式时,从pool中获取连接的阻塞最大时长。默认是连接池,默认永久阻塞。 //RT最大为1.5S //连接数最大为1024 //每个域名最多连接数64 //如果上述值,需要修改,请用户自己手动创建客户端, // 言外之意,这些参数是默认规范 RequestConfig defaultRequestConfig = RequestConfig.custom() .setConnectTimeout(configuration.getConnectionTimeout().intValue()) .setSocketTimeout(configuration.getSocketTimeout().intValue()) .setConnectionRequestTimeout(configuration.getConnectionRequestTimeout())//请求最大时长1.5S, .build(); builder.setDefaultRequestConfig(defaultRequestConfig); builder.setMaxConnTotal(configuration.getMaxConnections()); builder.setMaxConnPerRoute(128);//常量值 builder.evictExpiredConnections();//过期移除 builder.evictIdleConnections(10, TimeUnit.SECONDS);//空闲10秒移除 return builder.build(); } /** * 基于常规默认 * * @return */ public static CloseableHttpClient build() { HttpClientConfiguration configuration = HttpClientConfiguration.common(); return build(configuration); } }
相关推荐
Apache HttpComponents 是一个强大的Java库,提供了全面的HTTP客户端支持,包括文件上传功能。这篇博客文章(链接:https://eof.iteye.com/blog/2153595)可能详细介绍了如何利用Apache HttpClient实现这个功能。 ...
Apache HttpComponents客户端欢迎使用Apache HttpComponents项目的HttpClient组件。建筑说明有关从源代码进行构建的信息,请参阅 。依存关系HttpClient主模块需要与Java 7兼容的运行时,并且依赖于以下外部库:其他...
apache-httpcomponents-httpmime.jar
Apache HttpClient是一个流行的开源Java库,由Apache软件基金会维护,主要用于实现HTTP协议的客户端功能。本篇将深入探讨`org.apache.http`组件,特别是`httpcomponents-client-4.5.3`版本在Java POST HTTP开发中的...
在标题提到的`httpcomponents-client-4.2.5-bin.tar`中,我们找到了Apache HttpClient的特定版本4.2.5的二进制分发包,它通常包含了一系列的JAR文件,用于支持网络爬虫和其他需要与HTTP服务器交互的应用程序。...
这个压缩包文件"apache-httpcomponents-httpcore.jar.zip"包含了HTTPCore组件,它是Apache HTTP Components项目的基础部分,专注于提供低级别的HTTP传输机制。在本文中,我们将深入探讨HTTPCore的基本概念、功能以及...
commons-codec-1.11.jar commons-logging-1.2.jar fluent-hc-4.5.10.jar httpclient-4.5.10.jar httpclient-cache-4.5.10.jar httpclient-osgi-4.5.10.jar httpclient-win-4.5.10.jar ...jna-4.5.2.jar ...
标题中的"httpcomponents-client-4.5.6.rar"是一个压缩包文件,它是Apache HttpComponents项目的客户端组件的一个版本,具体是4.5.6版。HttpComponents是Java领域中用于处理HTTP协议的重要库,它提供了对HTTP协议的...
鸿蒙HttpComponents Client 是一个高性能开源库,专为HTTP协议交互设计,广泛应用于Web服务、网络应用程序及不断扩展的云计算领域。尽管标准Java与.NET库具备基本HTTP通信能力,但它们的功能与灵活性往往无法满足...
org.apache.httpcomponents.client4.11org.apache.httpcomponents.client4.11org.apache.httpcomponents.client4.11
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache...
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache...
标题中的"httpcomponents-client-4.5.3所需jar"指的是Apache HttpComponents客户端库的一个特定版本,4.5.3。这个库是Java开发者用来构建HTTP客户端应用的重要工具,它提供了全面的功能来处理HTTP协议,包括GET、...
Maven坐标:org.apache.httpcomponents:httpclient:4.5.13; 标签:apache、httpcomponents、httpclient、jar包、java、中文文档; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档...
本篇文章将深入探讨Apache HttpComponents的核心概念、功能以及在实际开发中的应用。 一、Apache HttpComponents概述 Apache HttpComponents是Apache软件基金会的一个项目,它提供了两个主要的模块:HttpClient和...
Maven坐标:org.apache.httpcomponents:httpcore-nio:4.4.12; 标签:apache、httpcomponents、httpcore、nio、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览...
Apache HttpComponents是一个强大的开源Java库,它为开发者提供了全面的HTTP客户端编程接口。这个库的主要目的是简化HTTP协议的处理,使开发人员能够高效地构建网络应用程序。"httpcomponents-client-4.5.1"是...
HTTPComponents客户端库是Apache软件基金会的一个重要项目,它为Java开发者提供了高效、灵活且可扩展的HTTP客户端API。这个库主要用于处理HTTP协议,包括发送HTTP请求和接收HTTP响应,是Java开发网络应用的必备工具...
《HTTPComponents客户端库4.0详解》 HTTPComponents是Apache软件基金会的一个项目,它提供了用于处理HTTP协议的高质量、高性能的Java库。其中,HTTPComponents客户端(httpcomponents-client)是针对HTTP客户端应用...
Maven坐标:org.apache.httpcomponents:httpclient:4.5.12; 标签:apache、httpcomponents、httpclient、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档...