HttpClient 常用方法封裝
簡介
在平時寫代碼中,經常需要對接口進行訪問,對於 http 協議 rest 風格的接口請求,大多使用 HttpClient 工具進行編寫,想着方便就尋思着把一些常用的方法進行封裝,便於平時快速的使用。
以下代碼封裝的常用方法,支持了http 和 https 兩種協議。
封裝代碼
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
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.HttpDelete;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @Description: httpclient常用方法封裝,
* @Author: ggf
* @Date: 2020/06/06
*/
public class HttpClientUtils {
/**
* 編碼方式
*/
private static final String ENCODING = "UTF-8";
/**
* 連接超時時間,60秒
*/
public static final int DEFAULT_CONNECT_TIMEOUT = 6000;
/**
* socket連接超時時間,60秒
*/
public static final int DEFAULT_READ_TIMEOUT = 6000;
/**
* 請求超時時間,60秒
*/
public static final int DEFAULT_CONNECT_REQUEST_TIMEOUT = 6000;
/**
* 最大連接數,默認為2
*/
private static final int MAX_TOTAL = 64;
/**
* 設置指向特定路由的並發連接總數,默認為2
*/
private static final int MAX_PER_ROUTE = 32;
private static RequestConfig requestConfig;
private static PoolingHttpClientConnectionManager connectionManager;
private static BasicCookieStore cookieStore;
private static HttpClientBuilder httpBuilder;
private static CloseableHttpClient httpClient;
private static CloseableHttpClient httpsClient;
private static SSLContext sslContext;
/**
* 創建SSLContext對象,用來繞過https證書認證實現訪問。
*/
static {
try {
sslContext = SSLContext.getInstance("TLS");
// 實現一個X509TrustManager接口,用於繞過驗證,不用修改裏面的方法
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] {tm}, null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 初始化httpclient對象,以及在創建httpclient對象之前的一些自定義配置。
*/
static {
// 自定義配置信息
requestConfig = RequestConfig.custom()
.setSocketTimeout(DEFAULT_READ_TIMEOUT)
.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT)
.setConnectionRequestTimeout(DEFAULT_CONNECT_REQUEST_TIMEOUT)
.build();
//設置協議http和https對應的處理socket鏈接工廠的對象
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", new PlainConnectionSocketFactory())
.register("https", new SSLConnectionSocketFactory(sslContext))
.build();
connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 設置cookie存儲對像,在需要獲取cookie信息時,可以使用這個對象。
cookieStore = new BasicCookieStore();
// 設置最大連接數
connectionManager.setMaxTotal(MAX_TOTAL);
// 設置路由並發數
connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
httpBuilder = HttpClientBuilder.create();
httpBuilder.setDefaultRequestConfig(requestConfig);
httpBuilder.setConnectionManager(connectionManager);
httpBuilder.setDefaultCookieStore(cookieStore);
// 實例化http 和 https的對象。
httpClient = httpBuilder.build();
httpsClient = httpBuilder.build();
}
/**
* 封裝無參數的get請求(http)
* @param url 請求url
* @return 返回對象HttpClientResult
*/
public static HttpClientResult doGet(String url) {
return doGet(url, false);
}
/**
* 封裝無參get請求,支持https協議
* @param url 請求url
* @param https 請求的是否是https協議,是:true 否false
* @return
*/
public static HttpClientResult doGet(String url, boolean https){
return doGet(url, null, null, https);
}
/**
* 封裝帶參數的get請求,支持https協議
* @param url 請求url
* @param params 請求參數
* @param https 是否是https協議
*/
public static HttpClientResult doGet(String url, Map<String, String> params, boolean https){
return doGet(url, null, params, https);
}
/**
* 封裝帶參數和帶請求頭信息的GET方法,支持https協議請求
* @param url 請求url
* @param headers 請求頭信息
* @param params 請求參數
* @param https 是否使用https協議
*/
public static HttpClientResult doGet(String url, Map<String, String> headers, Map<String, String> params, boolean https){
// 創建HttpGet
HttpGet httpGet = null;
// 創建httpResponse對象
CloseableHttpResponse httpResponse = null;
try {
// 創建訪問的地址
URIBuilder uriBuilder = new URIBuilder(url);
if (params != null) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
uriBuilder.setParameter(entry.getKey(), entry.getValue());
}
}
// 創建HTTP對象
httpGet = new HttpGet(uriBuilder.build());
httpGet.setConfig(requestConfig);
// 設置請求頭
setHeader(headers, httpGet);
// 使用不同的協議進行請求,返回自定義的響應對象
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpGet);
} else {
return getHttpClientResult(httpResponse, httpClient, httpGet);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 釋放資源
if (httpGet != null) {
httpGet.releaseConnection();
}
release(httpResponse);
}
return null;
}
/**
* POST不帶參數,只支持http協議
* @param url 請求url
*/
public static HttpClientResult doPost(String url) {
return doPost(url, Boolean.FALSE);
}
/**
* 封裝不帶參數的post請求,支持https協議
* @param url 請求url
* @param https 是否是https協議
*/
public static HttpClientResult doPost(String url, boolean https) {
return doPost(url, null, (Map<String, String>)null, https);
}
/**
* 帶參數的post請求,支持https協議
* @param url 請求url
* @param params 請求參數
* @param https 是否是https協議
*/
public static HttpClientResult doPost(String url, Map<String, String> params, boolean https) {
return doPost(url, null, params, https);
}
/**
* 帶參數和請求頭的POST請求,支持https
*
* @param url 請求url
* @param headers 請求頭
* @param params 請求參數,參數為K=V格式
* @param https 是否https協議
*/
public static HttpClientResult doPost(String url, Map<String, String> headers, Map<String, String> params, boolean https) {
// 創建HTTP對象
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
// 設置請求頭
setHeader(headers, httpPost);
// 封裝請求參數
setParam(params, httpPost);
// 創建httpResponse對象
CloseableHttpResponse httpResponse = null;
try {
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpPost);
} else {
return getHttpClientResult(httpResponse, httpClient, httpPost);
}
} finally {
httpPost.releaseConnection();
release(httpResponse);
}
}
/**
* 帶參數、帶請求頭的POST請求,支持https協議
*
* @param url 請求url
* @param headers 請求頭
* @param json 請求參數為json格式
* @param https 是否使用https協議
* @throws Exception
*/
public static HttpClientResult doPost(String url, Map<String, String> headers, String json, boolean https) {
// 創建HTTP對象
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(requestConfig);
// 設置請求頭
setHeader(headers, httpPost);
StringEntity stringEntity = new StringEntity(json, ENCODING);
stringEntity.setContentEncoding(ENCODING);
httpPost.setEntity(stringEntity);
// 創建httpResponse對象
CloseableHttpResponse httpResponse = null;
try {
if (https) {
return getHttpClientResult(httpResponse, httpsClient, httpPost);
} else {
return getHttpClientResult(httpResponse, httpClient, httpPost);
}
} finally {
httpPost.releaseConnection();
release(httpResponse);
}
}
/**
* 發送put請求;不帶請求參數
*
* @param url 請求地址
* @return
* @throws Exception
*/
public static HttpClientResult doPut(String url) {
return doPut(url);
}
/**
* 發送put請求;帶請求參數
*
* @param url 請求地址
* @param params 參數集合
* @return
* @throws Exception
*/
public static HttpClientResult doPut(String url, Map<String, String> params) {
HttpPut httpPut = new HttpPut(url);
httpPut.setConfig(requestConfig);
setParam(params, httpPut);
CloseableHttpResponse httpResponse = null;
try {
return getHttpClientResult(httpResponse, httpClient, httpPut);
} finally {
httpPut.releaseConnection();
release(httpResponse);
}
}
/**
* 發送delete請求,不帶請求參數
*
* @param url 請求url
* @return
* @throws Exception
*/
public static HttpClientResult doDelete(String url) {
HttpDelete httpDelete = new HttpDelete(url);
httpDelete.setConfig(requestConfig);
CloseableHttpResponse httpResponse = null;
try {
return getHttpClientResult(httpResponse, httpClient, httpDelete);
} finally {
httpDelete.releaseConnection();
release(httpResponse);
}
}
/**
* 發送delete請求,帶請求參數, 支持https協議
*
* @param url 請求url
* @param params 請求參數
* @param https 是否https
* @return
* @throws Exception
*/
public static HttpClientResult doDelete(String url, Map<String, String> params, boolean https) {
if (params == null) {
params = new HashMap<String, String>();
}
params.put("_method", "delete");
return doPost(url, params, https);
}
/**
* 獲取cookie信息
* @return 返回所有cookie集合
*/
public static List<Cookie> getCookies() {
return cookieStore.getCookies();
}
/**
* 設置封裝請求頭
*
* @param params 頭信息
* @param httpMethod 請求對象
*/
public static void setHeader(Map<String, String> params, HttpRequestBase httpMethod) {
// 封裝請求頭
if (null != params && !params.isEmpty()) {
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
// 設置到請求頭到HttpRequestBase對象中
httpMethod.setHeader(entry.getKey(), entry.getValue());
}
}
}
/**
* 封裝請求參數
*
* @param params 請求參數
* @param httpMethod 請求方法
*/
public static void setParam(Map<String, String> params, HttpEntityEnclosingRequestBase httpMethod) {
// 封裝請求參數
if (null != params && !params.isEmpty()) {
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
Set<Map.Entry<String, String>> entrySet = params.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
UrlEncodedFormEntity entity = null;
try {
entity = new UrlEncodedFormEntity(nvps, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 設置到請求的http對象中
httpMethod.setEntity(entity);
}
}
/**
* 獲得響應結果
*
* @param httpResponse 響應對象
* @param httpClient httpclient對象
* @param httpMethod 請求方法
* @return
* @throws Exception
*/
public static HttpClientResult getHttpClientResult(CloseableHttpResponse httpResponse, CloseableHttpClient httpClient, HttpRequestBase httpMethod) {
try {
// 執行請求
httpResponse = httpClient.execute(httpMethod);
// 獲取返回結果
if (httpResponse != null && httpResponse.getStatusLine() != null) {
String content = "";
if (httpResponse.getEntity() != null) {
content = EntityUtils.toString(httpResponse.getEntity(), ENCODING);
}
return new HttpClientResult(httpResponse.getStatusLine().getStatusCode(), content);
}
} catch (IOException e) {
e.printStackTrace();
}
return new HttpClientResult(HttpStatus.SC_INTERNAL_SERVER_ERROR);
}
/**
* 釋放資源
*
* @param httpResponse 響應對象
*/
public static void release(CloseableHttpResponse httpResponse) {
// 釋放資源
if (httpResponse != null) {
try {
httpResponse.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}