package com.jzq.common.http;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.jzq.common.CommonUtil;
|
import com.jzq.common.ResultInfo;
|
import com.jzq.common.exception.ResultInfoException;
|
import org.apache.commons.lang3.StringUtils;
|
import org.apache.http.*;
|
import org.apache.http.client.HttpRequestRetryHandler;
|
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.HttpGet;
|
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpRequestBase;
|
import org.apache.http.client.utils.URIBuilder;
|
import org.apache.http.config.ConnectionConfig;
|
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.conn.ssl.TrustSelfSignedStrategy;
|
import org.apache.http.entity.ContentType;
|
import org.apache.http.entity.mime.MultipartEntityBuilder;
|
import org.apache.http.entity.mime.content.ByteArrayBody;
|
import org.apache.http.entity.mime.content.FileBody;
|
import org.apache.http.entity.mime.content.InputStreamBody;
|
import org.apache.http.entity.mime.content.StringBody;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.LaxRedirectStrategy;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.message.BasicHeader;
|
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.protocol.ExecutionContext;
|
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.ssl.SSLContexts;
|
import org.apache.http.util.EntityUtils;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLException;
|
import javax.net.ssl.TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
import java.io.File;
|
import java.io.IOException;
|
import java.io.InterruptedIOException;
|
import java.io.UnsupportedEncodingException;
|
import java.net.ConnectException;
|
import java.net.URI;
|
import java.net.URISyntaxException;
|
import java.net.UnknownHostException;
|
import java.nio.charset.CodingErrorAction;
|
import java.security.KeyManagementException;
|
import java.security.KeyStore;
|
import java.security.KeyStoreException;
|
import java.security.NoSuchAlgorithmException;
|
import java.security.cert.CertificateException;
|
import java.security.cert.X509Certificate;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* http的请求服务类
|
* 也可以考虑使用spring restTemplate调用
|
*/
|
public class HttpClientUtils {
|
public static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
|
private static Object objTg = new Object();
|
private static HttpClientUtils httpClientUtils;
|
/**
|
* 默认连接超时时间
|
*/
|
private final static int DEFAULT_CONN_TIMEOUT = 6000;
|
/**最大重试次数*/
|
private final static int DEFAULT_RETRY_TIMES = 3;
|
|
private CloseableHttpClient client;
|
|
/**
|
* ssl trust管理
|
*/
|
public static class SSLTrustAllManager implements 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;
|
}
|
}
|
|
/**
|
* 初始化ssl管理
|
* @return
|
* @throws KeyStoreException
|
* @throws CertificateException
|
* @throws NoSuchAlgorithmException
|
* @throws IOException
|
* @throws KeyManagementException
|
*/
|
private SSLConnectionSocketFactory initSSLConnectionSocketFactory() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException {
|
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
trustStore.load(null, null);
|
SSLContext sslcontext = SSLContexts.custom()
|
.loadTrustMaterial(trustStore,
|
new TrustSelfSignedStrategy())
|
.build();
|
sslcontext.init(null, new TrustManager[] { new SSLTrustAllManager() }, null);
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
|
sslcontext,
|
//new String[] { "TLSv1","TLSv1.1","TLSv1.2","SSLv3"},//参考ProtocolVersion//这里写为null为所有
|
null,
|
null,
|
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
|
return sslsf;
|
}
|
|
|
public HttpClientUtils() throws Exception {
|
// 设置协议http和https对应的处理socket链接工厂的对象
|
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
|
.register("http", PlainConnectionSocketFactory.INSTANCE)
|
.register("https", initSSLConnectionSocketFactory())
|
.build();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
|
connManager.setValidateAfterInactivity(1000);
|
ConnectionConfig connectionConfig = ConnectionConfig.custom()
|
.setMalformedInputAction(CodingErrorAction.IGNORE)
|
.setUnmappableInputAction(CodingErrorAction.IGNORE)
|
.setCharset(Consts.UTF_8)
|
.build();
|
connManager.setDefaultConnectionConfig(connectionConfig);
|
connManager.setMaxTotal(100);
|
connManager.setDefaultMaxPerRoute(10);//最大路由深度,即301次数
|
|
//默认头信息,创建自定义的httpclient对象
|
List<Header> defaultHeaders=new ArrayList<Header>();
|
defaultHeaders.add(new BasicHeader("Accept","text/html,application/xhtml+xml,application/xml,application/json;q=0.9,*/*;q=0.8"));
|
defaultHeaders.add(new BasicHeader("Accept-Language","zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2"));
|
defaultHeaders.add(new BasicHeader("Connection","close"));
|
defaultHeaders.add(new BasicHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"));
|
//默认请求配置
|
RequestConfig requestConfig = RequestConfig.custom()
|
.setSocketTimeout(DEFAULT_CONN_TIMEOUT)
|
.setConnectTimeout(DEFAULT_CONN_TIMEOUT)
|
//.setProxy(new HttpHost("myotherproxy", 8080)) //设置代理
|
.setConnectionRequestTimeout(DEFAULT_CONN_TIMEOUT).build();
|
//重试拦截
|
HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
|
@Override
|
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
|
if (executionCount >= DEFAULT_RETRY_TIMES) {
|
//Do not retry if over max retry count
|
return false;
|
}
|
if (exception instanceof InterruptedIOException) {
|
// Timeout
|
return false;
|
}
|
if (exception instanceof UnknownHostException) {
|
// Unknown host
|
return false;
|
}
|
if (exception instanceof ConnectException) {
|
// Connection refused
|
return false;
|
}
|
if (exception instanceof SSLException) {
|
// SSL handshake exception
|
return false;
|
}
|
HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
|
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
|
if (idempotent) {
|
return true;
|
}
|
return false;
|
}
|
};
|
|
client = HttpClients.custom()
|
.setConnectionManager(connManager)
|
.setDefaultHeaders(defaultHeaders)
|
.setDefaultRequestConfig(requestConfig)
|
.setRetryHandler(myRetryHandler)
|
.setRedirectStrategy(new LaxRedirectStrategy())
|
.build();
|
}
|
/**
|
* init实例
|
* @return
|
*/
|
public static HttpClientUtils init(){
|
synchronized (objTg) {
|
if (httpClientUtils == null) {
|
try {
|
httpClientUtils = new HttpClientUtils();
|
} catch (Exception e) {
|
throw new ResultInfoException("ACCESS_SIGN_ERROR","httpClient初始化出错",e);
|
}
|
}
|
}
|
return httpClientUtils;
|
}
|
|
|
/**
|
* 工具类,通过url和params 生成url地址
|
* @param url
|
* @param params
|
* @return
|
* @throws URISyntaxException
|
*/
|
public static URI builderUrl(String url, Map<String, Object> params){
|
URIBuilder builder = null;
|
try {
|
builder = new URIBuilder(url);
|
if(params!=null&¶ms.size()>0){
|
for(String key: params.keySet()){
|
Object obj=params.get(key);
|
if(obj==null){continue;}
|
builder.setParameter(key, CommonUtil.parValNoErr(obj, String.class));
|
}
|
}
|
return builder.build();
|
} catch (URISyntaxException e) {
|
throw new ResultInfoException("HTTP_URL_FORMART","转换地址出错:"+url,e);
|
}
|
}
|
|
public static void fillHeader(HttpRequestBase request, Map<String, Object> heads){
|
//请求头
|
if (heads != null && heads.size() > 0) {
|
for (String key : heads.keySet()) {
|
request.addHeader(key, heads.get(key) + "");
|
}
|
}
|
}
|
/**
|
* get请求
|
* @param uri
|
* @param heads
|
* @param params
|
* @return
|
* @throws Exception
|
*/
|
public String getGet(String uri, Map<String, Object> heads, Map<String, Object> params) {
|
HttpGet request = new HttpGet(builderUrl(uri,params));
|
fillHeader(request,heads);
|
CloseableHttpResponse response = null;
|
try {
|
response = client.execute(request);
|
if (response.getStatusLine().getStatusCode() == 200) {
|
// 获得返回的字符串
|
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
return result;
|
} else {
|
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
result= StringUtils.isNotBlank(result)?result.substring(0,result.length()>200?200:result.length()) : "";
|
ResultInfo<String> res=new ResultInfo<String>();
|
res.setData(result);
|
res.setSuccess(false);
|
res.setResultCode(response.getStatusLine().getStatusCode()+"");
|
throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res));
|
}
|
} catch (IOException e) {
|
throw new ResultInfoException("EXCEPTION","网络请求失败",e);
|
} finally {
|
try {
|
response.close();
|
} catch (Exception e) {}
|
}
|
}
|
|
public byte[] getGetByte(String uri, Map<String, Object> heads, Map<String, Object> params) {
|
HttpGet request = new HttpGet(builderUrl(uri,params));
|
fillHeader(request,heads);
|
CloseableHttpResponse response = null;
|
try {
|
response = client.execute(request);
|
if (response.getStatusLine().getStatusCode() == 200) {
|
// 获得返回的字符串
|
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
return result;
|
} else {
|
ResultInfo<String> res=new ResultInfo<String>();
|
res.setSuccess(false);
|
res.setResultCode(response.getStatusLine().getStatusCode()+"");
|
throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res));
|
}
|
} catch (IOException e) {
|
throw new ResultInfoException("EXCEPTION","网络请求失败",e);
|
} finally {
|
try {
|
response.close();
|
} catch (Exception e) {}
|
}
|
}
|
|
/**
|
* 直接获取返回体,注意要手动关闭response
|
* @param uri
|
* @param heads
|
* @param params
|
* @return
|
*/
|
public CloseableHttpResponse getGetResponse(String uri, Map<String, Object> heads, Map<String, Object> params) throws IOException {
|
HttpGet request = new HttpGet(builderUrl(uri,params));
|
fillHeader(request,heads);
|
CloseableHttpResponse response = null;
|
response = client.execute(request);
|
return response;
|
}
|
|
/**
|
* 构建post的body信息,
|
* @param request
|
* @param params
|
* @param ifMutipart 是否启用富文件方式上传
|
*/
|
private void buildPostBody(HttpPost request, Map<String, Object> params, boolean ifMutipart){
|
if(ifMutipart){
|
//富文本请求
|
MultipartEntityBuilder meBuiler = MultipartEntityBuilder.create();
|
if (params != null && params.size() > 0) {
|
for (String key : params.keySet()) {
|
Object obj = params.get(key);
|
if(obj==null){
|
continue;
|
}else if (obj instanceof File) {
|
FileBody fb = new FileBody((File) obj);
|
meBuiler.addPart(key, fb);
|
} else if (obj instanceof ByteArrayBody) {
|
meBuiler.addPart(key, (ByteArrayBody) obj);
|
} else if (obj instanceof FileBody) {
|
meBuiler.addPart(key, (FileBody) obj);
|
} else if (obj instanceof InputStreamBody) {
|
meBuiler.addPart(key, (InputStreamBody) obj);
|
}else {
|
StringBody sb = new StringBody(CommonUtil.parValNoErrDef(obj, String.class, ""), ContentType.create("text/plain", "UTF-8"));
|
meBuiler.addPart(key, sb);
|
}
|
}
|
}
|
HttpEntity httpEntity = meBuiler.build();
|
request.setEntity(httpEntity);
|
}else{
|
//普通请求
|
List<NameValuePair> pList = new ArrayList<NameValuePair>();
|
if (params != null && params.size() > 0) {
|
for (String key : params.keySet()) {
|
Object obj=params.get(key);
|
if(obj==null){continue;}
|
pList.add(new BasicNameValuePair(key, obj + ""));
|
}
|
}
|
try {
|
request.setEntity(new UrlEncodedFormEntity(pList, "UTF-8"));
|
} catch (UnsupportedEncodingException e) {
|
throw new ResultInfoException("HTTP_REQ_ENCODE_ERROR","请求参数格式化出错",e);
|
}
|
}
|
}
|
|
/**
|
* post的上传请求
|
* @param uri
|
* @param heads
|
* @param params
|
* @return
|
* @throws Exception
|
*/
|
public String getPost(String uri, Map<String, Object> heads, Map<String, Object> params, boolean ifMutipart) {
|
HttpPost request = new HttpPost(uri);
|
fillHeader(request,heads);
|
buildPostBody(request,params,ifMutipart);
|
CloseableHttpResponse response = null;
|
try {
|
response = client.execute(request);
|
if (response.getStatusLine().getStatusCode() == 200) {
|
// 获得返回的字符串
|
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
return result;
|
} else {
|
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
result= StringUtils.isNotBlank(result) ?result.substring(0,result.length()>200?200:result.length()) : "";
|
ResultInfo<String> res=new ResultInfo<String>();
|
res.setData(result);
|
res.setSuccess(false);
|
res.setResultCode(response.getStatusLine().getStatusCode()+"");
|
throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res));
|
}
|
} catch (IOException e) {
|
throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e);
|
} finally {
|
try {
|
response.close();
|
} catch (Exception e) {}
|
}
|
}
|
|
/**
|
* post的上传请求,返回byte[]
|
* @param uri
|
* @param heads
|
* @param params
|
* @return
|
* @throws Exception
|
*/
|
public byte[] getPostByte(String uri, Map<String, Object> heads, Map<String, Object> params, boolean ifMutipart) {
|
HttpPost request = new HttpPost(uri);
|
fillHeader(request,heads);
|
buildPostBody(request,params,ifMutipart);
|
CloseableHttpResponse response = null;
|
try {
|
response = client.execute(request);
|
if (response.getStatusLine().getStatusCode() == 200) {
|
// 获得返回的byte[]
|
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
return result;
|
} else {
|
ResultInfo<String> res=new ResultInfo<String>();
|
res.setSuccess(false);
|
res.setResultCode(response.getStatusLine().getStatusCode()+"");
|
throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res));
|
}
|
} catch (IOException e) {
|
throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e);
|
} finally {
|
try {
|
response.close();
|
} catch (Exception e) {}
|
}
|
}
|
|
/**
|
* post的上传请求,返回CloseableHttpResponse,必须手动关闭
|
* @param uri
|
* @param heads
|
* @param params
|
* @return
|
* @throws Exception
|
*/
|
public CloseableHttpResponse getPostResponse(String uri, Map<String, Object> heads, Map<String, Object> params, boolean ifMutipart) {
|
HttpPost request = new HttpPost(uri);
|
fillHeader(request,heads);
|
buildPostBody(request,params,ifMutipart);
|
CloseableHttpResponse response = null;
|
try {
|
response = client.execute(request);
|
if (response.getStatusLine().getStatusCode() == 200) {
|
return response;
|
} else {
|
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
|
result= StringUtils.isNotBlank(result)?result.substring(0,result.length()>200?200:result.length()) : "";
|
ResultInfo<String> res=new ResultInfo<String>();
|
res.setData(result);
|
res.setSuccess(false);
|
res.setResultCode(response.getStatusLine().getStatusCode()+"");
|
throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res));
|
}
|
} catch (IOException e) {
|
throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e);
|
} finally {
|
try {
|
response.close();
|
} catch (Exception e) {}
|
}
|
}
|
}
|