基於HttpClient4.5.2實現的HttpClient工具類
阿新 • • 發佈:2019-01-04
1.maven依賴:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId >
<version>4.5.2</version>
</dependency>
2.HttpClientUtil工具類
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
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.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
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.ContentType;
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.util.EntityUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
/**
*
* @author Qian Wenjin
*
*/
public class HttpClientUtil {
private static final Logger LOG = LogManager.getLogger(HttpClientUtil.class);
private static final int CONNECT_TIMEOUT = 5000;//設定超時毫秒數
private static final int SOCKET_TIMEOUT = 10000;//設定傳輸毫秒數
private static final int REQUESTCONNECT_TIMEOUT = 3000;//獲取請求超時毫秒數
private static final int CONNECT_TOTAL = 200;//最大連線數
private static final int CONNECT_ROUTE = 20;//設定每個路由的基礎連線數
private static final int VALIDATE_TIME = 30000;//設定重用連線時間
private static final String RESPONSE_CONTENT = "通訊失敗";
private static PoolingHttpClientConnectionManager manager = null;
private static CloseableHttpClient client = null;
static {
ConnectionSocketFactory csf = PlainConnectionSocketFactory.getSocketFactory();
LayeredConnectionSocketFactory lsf = createSSLConnSocketFactory();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", csf).register("https", lsf).build();
manager = new PoolingHttpClientConnectionManager(registry);
manager.setMaxTotal(CONNECT_TOTAL);
manager.setDefaultMaxPerRoute(CONNECT_ROUTE);
manager.setValidateAfterInactivity(VALIDATE_TIME);
SocketConfig config = SocketConfig.custom().setSoTimeout(SOCKET_TIMEOUT).build();
manager.setDefaultSocketConfig(config);
RequestConfig requestConf = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
.setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
client = HttpClients.custom().setConnectionManager(manager).setDefaultRequestConfig(requestConf).setRetryHandler(
//實現了HttpRequestRetryHandler介面的
//public boolean retryRequest(IOException exception, int executionCount, HttpContext context)方法
(exception, executionCount, context) -> {
if(executionCount >= 3)
return false;
if(exception instanceof NoHttpResponseException)//如果伺服器斷掉了連線那麼重試
return true;
if(exception instanceof SSLHandshakeException)//不重試握手異常
return false;
if(exception instanceof InterruptedIOException)//IO傳輸中斷重試
return true;
if(exception instanceof UnknownHostException)//未知伺服器
return false;
if(exception instanceof ConnectTimeoutException)//超時就重試
return true;
if(exception instanceof SSLException)
return false;
HttpClientContext cliContext = HttpClientContext.adapt(context);
HttpRequest request = cliContext.getRequest();
if(!(request instanceof HttpEntityEnclosingRequest))
return true;
return false;
}).build();
if(manager!=null && manager.getTotalStats()!=null)
LOG.info("客戶池狀態:"+manager.getTotalStats().toString());
}
private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
SSLConnectionSocketFactory sslsf = null;
SSLContext context;
try {
context = SSLContext.getInstance(SSLConnectionSocketFactory.TLS);
sslsf = new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE);
} catch (NoSuchAlgorithmException e) {
LOG.error("SSL上下文建立失敗,由於" + e.getLocalizedMessage());
e.printStackTrace();
}
return sslsf;
}
private String res(HttpRequestBase method) {
HttpClientContext context = HttpClientContext.create();
CloseableHttpResponse response = null;
String content = RESPONSE_CONTENT;
try {
response = client.execute(method, context);//執行GET/POST請求
HttpEntity entity = response.getEntity();//獲取響應實體
if(entity!=null) {
Charset charset = ContentType.getOrDefault(entity).getCharset();
content = EntityUtils.toString(entity, charset);
EntityUtils.consume(entity);
}
} catch(ConnectTimeoutException cte) {
LOG.error("請求連線超時,由於 " + cte.getLocalizedMessage());
cte.printStackTrace();
} catch(SocketTimeoutException ste) {
LOG.error("請求通訊超時,由於 " + ste.getLocalizedMessage());
ste.printStackTrace();
} catch(ClientProtocolException cpe) {
LOG.error("協議錯誤(比如構造HttpGet物件時傳入協議不對(將'http'寫成'htp')or響應內容不符合),由於 " + cpe.getLocalizedMessage());
cpe.printStackTrace();
} catch(IOException ie) {
LOG.error("實體轉換異常或者網路異常, 由於 " + ie.getLocalizedMessage());
ie.printStackTrace();
} finally {
try {
if(response!=null) {
response.close();
}
} catch(IOException e) {
LOG.error("響應關閉異常, 由於 " + e.getLocalizedMessage());
}
if(method!=null) {
method.releaseConnection();
}
}
return content;
}
public String get(String url) {
HttpGet get = new HttpGet(url);
return res(get);
}
public String get(String url, String cookie) {
HttpGet get = new HttpGet(url);
if(StringUtils.isNotBlank(cookie))
get.addHeader("cookie", cookie);
return res(get);
}
public byte[] getAsByte(String url) {
return get(url).getBytes();
}
public String getHeaders(String url, String cookie, String headerName) {
HttpGet get = new HttpGet(url);
if(StringUtils.isNotBlank(cookie))
get.addHeader("cookie", cookie);
res(get);
Header[] headers = get.getHeaders(headerName);
return headers == null ? null : headers.toString();
}
public String getWithRealHeader(String url) {
HttpGet get = new HttpGet(url);
get.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;");
get.addHeader("Accept-Language", "zh-cn");
get.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");
get.addHeader("Keep-Alive", "300");
get.addHeader("Connection", "Keep-Alive");
get.addHeader("Cache-Control", "no-cache");
return res(get);
}
public String post(String url, Map<String, String> param, String cookie) {
HttpPost post = new HttpPost(url);
param.keySet().stream().forEach(key -> {
String value = param.get(key);
if(value!=null)
post.addHeader(key, value);
});
if(StringUtils.isNotBlank(cookie))
post.addHeader("cookie", cookie);
return res(post);
}
public String post(String url, String data) {
HttpPost post = new HttpPost(url);
if(StringUtils.isNotBlank(data))
post.addHeader("Content-Type", "application/json");
post.setEntity(new StringEntity(data,ContentType.APPLICATION_JSON));
return res(post);
}
public String post(String url, Map<String, String> param, String cookie, Map<String, String> headers) {
HttpPost post = new HttpPost(url);
String reqEntity = "";
for(Entry<String, String> entry:param.entrySet()) {
post.addHeader(entry.getKey(), entry.getValue());
try {
reqEntity += entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "utf-8") + "&";
} catch (UnsupportedEncodingException e) {
LOG.error("請求實體轉換異常,不支援的字符集,由於 " + e.getLocalizedMessage());
e.printStackTrace();
}
}
try {
post.setEntity(new StringEntity(reqEntity));
} catch (UnsupportedEncodingException e) {
LOG.error("請求設定實體異常,不支援的字符集, 由於 " + e.getLocalizedMessage());
e.printStackTrace();
}
if(StringUtils.isNotEmpty(cookie))
post.addHeader("cookie", cookie);
return res(post);
}
}
4.注意,jdk版本要求1.8以上
ok~