@Configuration
@EnableConfigurationProperties(HttpClientProperties.class)
@ConditionalOnProperty(prefix = "myserver.httpclient", value = "enabled", havingValue = "true")
public class HttpClientConfig {
@Autowired
HttpClientProperties httpClientProperties;
@Bean
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();
pool.setDefaultMaxPerRoute(httpClientProperties.getDefaultMaxPerRoute());
pool.setMaxTotal(httpClientProperties.getMaxTotal());
new HttpClientPoolIdleConnectionMonitorThread(pool, httpClientProperties).start();
return pool;
}
@Bean
HttpClientBuilder httpClientBuilder(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager) {
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setConnectionManager(poolingHttpClientConnectionManager);
return builder;
}
@Bean
CloseableHttpClient getHttpClient(HttpClientBuilder httpClientBuilder) {
CloseableHttpClient httpClient = httpClientBuilder.build();
return httpClient;
}
@Bean
HttpUtils getHttpUtils(CloseableHttpClient httpClient) {
if (!httpClientProperties.getPool()) {
httpClient = HttpClients.createDefault();
}
HttpUtils httpUtils = new HttpUtils(httpClient, httpClientProperties.getPool());
return httpUtils;
}
}
public class HttpClientPoolIdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
private HttpClientProperties httpClientProperties;
public HttpClientPoolIdleConnectionMonitorThread(HttpClientConnectionManager connMgr, HttpClientProperties httpClientProperties) {
super();
this.connMgr = connMgr;
this.httpClientProperties = httpClientProperties;
}
@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(httpClientProperties.getPoolIdleConnectionMonitor().getWaitTime());
connMgr.closeExpiredConnections();
connMgr.closeIdleConnections(httpClientProperties.getPoolIdleConnectionMonitor().getCloseIdleTime(), TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
}
}
public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}
@Log4j2
@Data
public class HttpUtils {
private static final int HTTPCLIENT_TIMEOUT = 60000;
private static Charset DEFAULT_UTF8 = StandardCharsets.UTF_8;
private CloseableHttpClient httpClient;
private boolean isPool;
public HttpUtils() {
this(HttpClients.createDefault(), false);
}
public HttpUtils(CloseableHttpClient httpClient, boolean isPool) {
super();
this.httpClient = httpClient;
this.isPool = isPool;
}
public BiStringEntry post(String sendURL, Map<String, String> params) {
if (!this.isPool) {
this.httpClient = HttpClients.createDefault();
}
return post(sendURL, getNameValueList(params), DEFAULT_UTF8, null);
}
public BiStringEntry post(String sendURL, String entityContent) {
return post(sendURL, new StringEntity(entityContent, DEFAULT_UTF8));
}
public BiStringEntry post(String sendURL, List<NameValuePair> nameValueList, Charset encoding, String
contentType) {
return post(sendURL, getUrlEncoded(nameValueList, encoding, contentType));
}
public BiStringEntry post(String sendURL, HttpEntity httpEntity) {
BiStringEntry result = new BiStringEntry(BiStringEntry.ERROR, "");
Long longTime = System.currentTimeMillis();
result.setExt(longTime);
CloseableHttpResponse response = null;
HttpPost httpPost = null;
HttpEntity respEntity = null;
try {
httpPost = new HttpPost(sendURL);
httpPost.setHeader(HttpHeaders.ACCEPT_LANGUAGE, "zh-cn");
RequestConfig config = RequestConfig.custom().setSocketTimeout(HTTPCLIENT_TIMEOUT)
.setConnectionRequestTimeout(HTTPCLIENT_TIMEOUT).setConnectTimeout(HTTPCLIENT_TIMEOUT).build();
httpPost.setConfig(config);
httpPost.setEntity(httpEntity);
response = httpClient.execute(httpPost);
if (response == null) {
return result;
}
Integer respStatus = response.getStatusLine().getStatusCode();
try {
if (HttpStatus.SC_OK == respStatus) {
result.setCode(BiStringEntry.SUCCESS);
respEntity = response.getEntity();
if (respEntity != null) {
String msg = EntityUtils.toString(respEntity, DEFAULT_UTF8);
result.setMsg(msg);
}
} else {
result.put(BiStringEntry.ERROR, response.getStatusLine().toString());
}
} finally {
if (respEntity != null) {
EntityUtils.consume(respEntity);
}
try {
response.close();
} catch (IOException e) {
log.error("HttpUtils response exception", e);
}
}
} catch (Exception e) {
log.error("HttpUtils exception", e);
result.put(BiStringEntry.ERROR, e.getMessage());
} finally {
if (null != httpPost) {
httpPost.releaseConnection();
httpPost = null;
}
if (!isPool) {
try {
httpClient.close();
} catch (IOException e) {
log.error("HttpUtils close exception", e);
}
}
}
return result;
}
public static List<NameValuePair> getNameValueList(Map<String, String> params) {
List<NameValuePair> result = new ArrayList<NameValuePair>();
if (null != params && !params.isEmpty()) {
Set<Map.Entry<String, String>> paramsSet = params.entrySet();
for (Map.Entry<String, String> entry : paramsSet) {
result.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
}
return result;
}
private static UrlEncodedFormEntity getUrlEncoded(List<NameValuePair> nvps, Charset encoding, String
contentType) {
if (nvps == null) {
nvps = new ArrayList<>();
}
UrlEncodedFormEntity result = new UrlEncodedFormEntity(nvps, encoding);
if (null != contentType && !contentType.isEmpty()) {
result.setContentType(contentType);
}
return result;
}
}
@Data
@ConfigurationProperties(prefix = "myserver.httpclient.poolmanager")
public class HttpClientProperties {
private Integer maxTotal = 400;
private Integer defaultMaxPerRoute = 20;
private Boolean pool = true;
private PoolIdleConnectionMonitor poolIdleConnectionMonitor;
@Data
public static class PoolIdleConnectionMonitor {
private Integer waitTime = 5000;
private Integer closeIdleTime = 30;
}
}