1. 程式人生 > 實用技巧 >Httpclient工具類封裝

Httpclient工具類封裝

配置連線工廠

package org.common.framework.component.httpclient.config;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.config.RequestConfig;
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.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.common.framework.component.httpclient.consts.HttpConstants;

/**
 * httpclient連線工廠
 */
public class HttpClientConnectFactory {
	
	private static PoolingHttpClientConnectionManager cm = null;
	
	/**
	 * 初始化連線池
	 */
	static {
		SSLContext sslcontext;
		try {
			sslcontext = createIgnoreVerifySSL();
			ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
			Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register(HttpConstants.HTTP_PROTOCOL, plainsf)
                    .register(HttpConstants.HTTPS_PROTOCOL,getSSLConnectionSocketFactory(sslcontext))
                    .build();
			cm = new PoolingHttpClientConnectionManager(registry);
			cm.setMaxTotal(HttpConstants.MAX_TOTAL_POOL);
			cm.setDefaultMaxPerRoute(HttpConstants.MAX_CONPERROUTE);
		} catch (Exception e) {
			e.getStackTrace();
		}
	}
	
	/**
	 * 獲取httpclient連線
	 * @return
	 */
	public static CloseableHttpClient getHttpClient() {
		RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(HttpConstants.CONNECTION_REQUEST_TIMEOUT)
                .setConnectTimeout(HttpConstants.CONNECT_TIMEOUT)
                .setSocketTimeout(HttpConstants.SOCKET_TIMEOUT)
                .build();
		CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm)
                .setDefaultRequestConfig(requestConfig)
                .setRetryHandler(new MyHttpRequestRetryHandler())
                .setConnectionManagerShared(true)
                .build();
		return httpClient;
	}
	
	/**
	 * 建立sslcontext
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws KeyManagementException
	 */
	private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
		SSLContext sc = SSLContext.getInstance(HttpConstants.SSL_CONTEXT);
		X509TrustManager trustManager = new X509TrustManager(){
			public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				
			}
			public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
				
			}
			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		sc.init(null, new TrustManager[] { trustManager }, null);
		return sc; 
	}
	
	/**
	 * getSSLConnectionSocketFactory
	 * @param sslcontext
	 * @return
	 */
	private static ConnectionSocketFactory getSSLConnectionSocketFactory(SSLContext sslcontext) {
		return new SSLConnectionSocketFactory(sslcontext,NoopHostnameVerifier.INSTANCE);
	}
	

}

配置重試處理

package org.common.framework.component.httpclient.config;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.UnknownHostException;

import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;

import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.protocol.HttpContext;

/**
 * 定義重試處理機制
 */
public class MyHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {

	private int retry_times = 3;

	public MyHttpRequestRetryHandler() {
		super();
	}

	/**
	 * 覆蓋預設的重試次數及重試標誌
	 * @param retry_times
	 * @param retryFlag
	 */
	public MyHttpRequestRetryHandler(int retry_times) {
		super();
		this.retry_times = retry_times;
	}

	/**
	 * 檢查重試次數 檢查連線異常原因
	 */
	@Override
	public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
		if (executionCount >= retry_times) {// 如果已經重試了3次,就放棄
			return false;
		}
		if (exception instanceof NoHttpResponseException) {// 如果伺服器丟掉了連線,那麼就重試
			return true;
		}
		if (exception instanceof InterruptedIOException) {// 超時
			return true;
		}
		if (exception instanceof SSLHandshakeException) {// 不要重試SSL握手異常
			return false;
		}
		if (exception instanceof UnknownHostException) {// 目標伺服器不可達
			return false;
		}
		if (exception instanceof ConnectTimeoutException) {// 連線被拒絕
			return false;
		}
		if (exception instanceof SSLException) {// ssl握手異常
			return false;
		}
		HttpClientContext clientContext = HttpClientContext.adapt(context);
		HttpRequest request = clientContext.getRequest();
		// 如果請求是冪等的,就再次嘗試
		if (!(request instanceof HttpEntityEnclosingRequest)) {
			return true;
		}
		return false;
	}

}

定義http工具類

依賴-CustomHttpMethod

package org.common.framework.component.httpclient.consts;

/**
 *	 自定義請求型別
 */
public enum CustomHttpMethod {

	GET, POST, DELETE, PUT
	
}

依賴-HttpConstants

package org.common.framework.component.httpclient.consts;

/**
 * http請求常量
 */
public interface HttpConstants {
	
	/**
	 * 連線池最大連線數
	 */
	int MAX_TOTAL_POOL = 256;
	
	/**
	 * 每路連線最多連線數
	 */
	int MAX_CONPERROUTE = 32;
	
	/**
	 * socket超時時間
	 */
	int SOCKET_TIMEOUT = 60 * 1000;

	/**
	 * 連線請求超時時間
	 */
	int CONNECTION_REQUEST_TIMEOUT = 5 * 1000;

	/**
	 * 連線超時時間
	 */
	int CONNECT_TIMEOUT = 5 * 1000;
	
	/**
	 * http協議
	 */
	String HTTP_PROTOCOL = "http";

	/**
	 * https協議
	 */
	String HTTPS_PROTOCOL = "https";
	
	/**
	 * sslv3
	 */
	String SSL_CONTEXT = "SSLv3";

	/**
	 * utf-8編碼
	 */
	String CHARSET_UTF_8 = "UTF-8";

	/**
	 * application/json
	 */
	String CONTENT_TYPE_JSON = "application/json";
	
	/**
	 * content-type
	 */
	String CONTENT_TYPE = "Content-Type";
}

請求配置類-HttpRequestConfigUtil

package org.common.framework.component.httpclient.util;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.common.framework.component.httpclient.consts.HttpConstants;

/**
 *	 請求配置的公共
 */
public class HttpRequestConfigUtil {
	
	/**
	 * 返回預設的類容型別【application/json】
	 * 
	 * @return
	 */
	protected static String getDefaultContentType() {
		return HttpConstants.CONTENT_TYPE_JSON;
	}

	/**
	 * 設定預設的content-type: application/json
	 */
	protected static void setContentTypeApplicationJson(HttpRequestBase httpBase) {
		httpBase.setHeader(HttpConstants.CONTENT_TYPE, HttpConstants.CONTENT_TYPE_JSON);
	}

	/**
	 * 設定content-Type
	 */
	protected static void setContentType(HttpRequestBase httpBase, String contentType) {
		httpBase.setHeader(HttpConstants.CONTENT_TYPE, contentType);
	}

	/**
	 * 設定請求體
	 */
	protected static void setHttpBody(HttpEntityEnclosingRequestBase httpRequest, String body) {
		if(StringUtils.isBlank(body)) {
			return;
		}
		StringEntity entity = new StringEntity(body, HttpConstants.CHARSET_UTF_8);
		entity.setContentEncoding(HttpConstants.CHARSET_UTF_8);
		entity.setContentType(HttpConstants.CHARSET_UTF_8);
		httpRequest.setEntity(entity);
	}

	/**
	 * 設定頭部引數
	 * 
	 * @param httpBase
	 * @param map
	 */
	protected static void setHeader(HttpRequestBase httpBase, Map<String, String> map) {
		if (map == null || map.size() == 0) {
			return;
		}
		for (String item : map.keySet()) {
			httpBase.setHeader(item, map.get(item));
		}
	}
	
}

請求傳送類-BaseHttpUtil

package org.common.framework.component.httpclient.util;

import java.lang.reflect.Type;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
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.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.common.framework.component.httpclient.config.HttpClientConnectFactory;
import org.common.framework.component.httpclient.consts.CustomHttpMethod;

import com.alibaba.fastjson.JSON;

/**
 * http抽象類,繼承工具類的公共函式
 * @author Administrator
 *
 */
public class BaseHttpUtil extends HttpRequestConfigUtil {

	/**
	 * 建立請求物件 httpRequestBase
	 * 
	 * @param Method
	 * @param url
	 * @return
	 */
	protected static HttpRequestBase createHttpRequestBase(CustomHttpMethod Method, String url) {
		switch (Method) {
		case POST:
			return new HttpPost(url);
		case GET:
			return new HttpGet(url);
		case PUT:
			return new HttpPut(url);
		case DELETE:
			return new HttpDelete(url);
		default:
			return new HttpGet(url);
		}
	}
	
	/**
	 * send請求
	 * @param <T>
	 * @param url
	 * @param header
	 * @param content
	 * @param type
	 * @return
	 */
	protected static String exec( String url, CustomHttpMethod method, Map<String, String> header, String contentType, String body) {
		CloseableHttpClient httpClient = HttpClientConnectFactory.getHttpClient();
		HttpRequestBase httpBase = createHttpRequestBase(method, url);
		setHeader(httpBase, header);
		setContentType(httpBase, contentType);
		if (httpBase instanceof HttpEntityEnclosingRequestBase) {
			setHttpBody((HttpEntityEnclosingRequestBase) httpBase, body);
		}
		CloseableHttpResponse response = null;
		try {
			response = httpClient.execute(httpBase);
			response.getStatusLine().getStatusCode();
			HttpEntity httpEntity = response.getEntity();
			return EntityUtils.toString(httpEntity,"utf-8");
		}catch (Exception e) {
			e.printStackTrace();
			System.err.println("httpGetUtil error : {}" + e.getMessage());
		}
		return JSON.toJSONString(response);
	}
	
	
	/**
	 * 處理響應值
	 * @param <T>
	 * @param <B>
	 * @param apiResult
	 * @param defaultResult
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T handleResponse(String apiResult, T defaultResult, Type type) {
		if(StringUtils.isBlank(apiResult)) {
			return defaultResult;
		}
		try {
			return (T)JSON.parseObject(apiResult, type); 
		} catch (Exception e) {
			return defaultResult;
		}
	}
	
}

多參工具類-MultiHttpUtil

package org.common.framework.component.httpclient.util;

import java.util.Map;

import org.common.framework.component.httpclient.consts.CustomHttpMethod;

/**
 * Http 多種 請求方式定義
 */
public class MultiHttpUtil extends BaseHttpUtil {

	/**
	 * exec請求,通過以下引數獲取資料
	 * @param url   請求地址
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url) {
		return exec(customHttpMethod, url, null, getDefaultContentType(), null);
	}
	
	/**
	 * exec請求,通過以下引數獲取資料
	 * @param url   請求地址
	 * @param header  請求頭部引數
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url, Map<String, String> header) {
		return exec(customHttpMethod, url, header, getDefaultContentType(), null);
	}
	
	
	/**
	 * exec請求,通過以下引數獲取資料 content-Type 預設 application/json
	 * @param url   請求地址
	 * @param body  請求內容
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url, String body) {
		return exec(customHttpMethod, url, null, getDefaultContentType(), body);
	}
	
	/**
	 * exec請求,通過以下引數獲取資料 
	 * @param url   請求地址
	 * @param contentType  請求內容體型別
	 * @param body  請求內容
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url, String contentType, String body) {
		return exec(customHttpMethod, url, null, contentType, body);
	}
	
	/**
	 * exec請求,通過以下引數獲取資料 content-Type 預設 application/json
	 * @param url   請求地址
	 * @param header  請求頭部引數
	 * @param body  請求內容
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url, Map<String, String> header, String body) {
		return exec(customHttpMethod, url, header, getDefaultContentType(), body);
	}
	
	/**
	 * exec請求,通過以下引數獲取資料
	 * @param url   請求地址
	 * @param header  請求頭部引數
	 * @param contentType  請求內容體型別
	 * @param body  請求內容
	 * @return
	 */
	public static String exec(CustomHttpMethod customHttpMethod, String url, Map<String, String> header, String contentType, String body) {
		return exec(url, customHttpMethod, header, contentType, body);
	}
	
}

pom

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.nblh.framework</groupId>
	<artifactId>common-utils</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<dependencies>
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.7</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.6</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.30</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.0</version>
			</plugin>
		</plugins>
	</build>

</project>