Apache HttpClient 4.5 在Springboot中使用
ConnectionRequestTimeout
httpclient使用连接池来管理连接,这个时间就是从连接池获取连接的超时时间,可以想象下数据库连接池
ConnectTimeout
连接建立时间,三次握手完成时间
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.12</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.13</version>
</dependency>
然后新建httpclient类:
在dopost中可以根据业务自定义逻辑
@Slf4j
@Service
public class HttpClientFactory {
@Autowired
HttpClientConfig httpClientConfig;
private PoolingHttpClientConnectionManager poolConnManager;
// 线程安全,所有的线程都可以使用它一起发送http请求
private CloseableHttpClient httpClient;
@PostConstruct
public void init() {
try {
log.info("init http client start, default config is {}", httpClientConfig);
SSLConnectionSocketFactory trustAll = buildSSLContext();
// 配置同时支持 HTTP 和 HTTPS
// 一个httpClient对象对于https仅会选用一个SSLConnectionSocketFactory
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().
register("http", PlainConnectionSocketFactory.getSocketFactory()).
register("https", trustAll).build();
// 初始化连接管理器
poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolConnManager.setMaxTotal(httpClientConfig.getPollMaxTotal());// 同时最多连接数
// 设置最大路由
poolConnManager.setDefaultMaxPerRoute(httpClientConfig.getPollMaxPeerRouter());
httpClient = getConnection();
log.info("init http client finish");
} catch (Exception e) {
log.error("", e);
}
}
public CloseableHttpClient getConnection() {
RequestConfig config = RequestConfig.custom().setConnectTimeout(httpClientConfig.getConnectTimeout())
.setConnectionRequestTimeout(httpClientConfig.getConnectionRequestTimeout())
.setSocketTimeout(httpClientConfig.getResponseTimeout())
.build();
return HttpClients.custom()
// 设置连接池管理
.setConnectionManager(poolConnManager)
.setDefaultRequestConfig(config).build();
}
public String doGet(String url) {
return this.doGet(url, Collections.EMPTY_MAP, Collections.EMPTY_MAP);
}
public String doGet(String url, Map<String, Object> params) {
return this.doGet(url, Collections.EMPTY_MAP, params);
}
public String doGet(String url, Map<String, String> headers, Map<String, Object> params) {
// *) 构建GET请求头
String apiUrl = getUrlWithParams(url, params);
HttpGet httpGet = new HttpGet(apiUrl);
// *) 设置header信息
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpGet.addHeader(entry.getKey(), entry.getValue());
}
}
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
if (response == null || response.getStatusLine() == null) {
return null;
}
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity entityRes = response.getEntity();
if (entityRes != null) {
return EntityUtils.toString(entityRes, "UTF-8");
}
}
return null;
} catch (IOException e) {
log.error("", e);
}
return null;
}
public HttpServerResponseDTO doPost(String apiUrl, String body, int connectionTimeOut, Integer contentTypeEnum, String pemBody) {
return doPost(apiUrl, Collections.EMPTY_MAP, body, connectionTimeOut, contentTypeEnum);
}
public HttpServerResponseDTO doPost(String apiUrl, Map<String, String> headers, String body,Integer contentTypeEnum) {
CloseableHttpClient currentHttpClient = httpClient;
HttpPost httpPost = new HttpPost(apiUrl);
// *) 配置请求headers
if (headers != null && headers.size() > 0) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
httpPost.addHeader(entry.getKey(), entry.getValue());
}
}
ContentTypeEnum contentType = ContentTypeEnum.getDataSourceEnum(contentTypeEnum);
// *) 配置请求参数
httpPost.setEntity(new StringEntity(body, ContentType.create(contentType.getDesc(), Consts.UTF_8)));
httpPost.setConfig(buildRequestConfig());
try (CloseableHttpResponse response = currentHttpClient.execute(httpPost)) {
if (response == null || response.getStatusLine() == null) {
return HttpServerResponseDTO.builder()
.statusCode(Constants.HTTP_CLIENT_ERROR)
.build();
}
HttpEntity httpEntity = response.getEntity();
String contentTypeString = httpEntity.getContentType() == null ? null : httpEntity.getContentType().getValue();
String connection = getHeaderValue(response, "Connection");
String server = getHeaderValue(response, "Server");
String date = getHeaderValue(response, "Date");
String pragma = getHeaderValue(response, "pragma");
return HttpServerResponseDTO.builder()
.statusCode(response.getStatusLine().getStatusCode())
.body(EntityUtils.toString(response.getEntity(), UTF_8))
.contentType(contentTypeString)
.connection(connection)
.server(server)
.date(date)
.pragma(pragma)
.build();
} catch (IOException e) {
log.error("", e);
return HttpServerResponseDTO.builder().statusCode(Constants.HTTP_CLIENT_ERROR).statusMessage(e.getMessage()).build();
}
}
private String getUrlWithParams(String url, Map<String, Object> params) {
boolean first = true;
StringBuilder sb = new StringBuilder(url);
for (String key : params.keySet()) {
char ch = '&';
if (first) {
ch = '?';
first = false;
}
String value = params.get(key).toString();
try {
String sval = URLEncoder.encode(value, "UTF-8");
sb.append(ch).append(key).append("=").append(sval);
} catch (UnsupportedEncodingException e) {
log.error("", e);
}
}
return sb.toString();
}
public SSLConnectionSocketFactory buildSSLContext() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, KeyManagementException {
SSLContext sslcontext = SSLContexts.custom()
//忽略掉对服务器端证书的校验
.loadTrustMaterial((TrustStrategy) (chain, authType) -> true)
.build();
return new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1", "TLSv1.1", "TLSv1.2"},
null,
NoopHostnameVerifier.INSTANCE);
}
private RequestConfig buildRequestConfig() {
int connectionOut = httpClientConfig.getConnectTimeout();
return RequestConfig.custom().setConnectTimeout(connectionOut)
.setConnectionRequestTimeout(httpClientConfig.getConnectionRequestTimeout())
.setSocketTimeout(connectionOut)
.build();
}
private String getHeaderValue(CloseableHttpResponse response, String key) {
return response.getFirstHeader(key) == null ?
null : response.getFirstHeader(key).getValue();
}
}
调用方式:
@Autowired
HttpClientFactory httpClientFactory;
HttpServerResponseDTO httpServerResponseDTO = httpClientFactory.doPost(url, headersMap, body, httpConfigEntity.getContentType(), httpConfigEntity.getTls());