第一种写法:
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.KeyManagementException;
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;
import javax.activation.MimetypesFileTypeMap;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
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.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
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.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import lombok.extern.slf4j.Slf4j;import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;
@Slf4j
public class HttpclientUtils {
private final static int CONNECT_TIMEOUT = 4000; // 连接超时毫秒
private final static int SOCKET_TIMEOUT = 30000; // 传输超时毫秒
private final static int REQUESTCONNECT_TIMEOUT = 3000; // 获取请求超时毫秒
private final static String ENCODE_CHARSET = "utf-8"; // 响应报文解码字符集
static class RetryHandler implements HttpRequestRetryHandler {
@Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if (executionCount >= 3) {
// 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 ConnectTimeoutException) {
// Connection refused
return false;
}
if (exception instanceof SSLException) {
// SSL handshake exception
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// Retry if the request is considered idempotent
return true;
}
return false;
}
};
public static CloseableHttpClient createSSLClientDefault(HttpHost proxy) {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
// 信任所有
@Override
public boolean isTrusted(X509Certificate【】 chain, String authType) throws CertificateException {
//代码效果参考:http://www.lyjsj.net.cn/wx/art_22942.html
return true;}
}).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
HttpRequestRetryHandler retryHandler = new RetryHandler();
Builder buider = RequestConfig.custom().setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT);
if (null //代码效果参考:http://www.lyjsj.net.cn/wz/art_22940.html
!= proxy) {buider.setProxy(proxy);
}
RequestConfig requestConfig = buider.build();
HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfig).setRetryHandler(retryHandler).build();
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
log.error(e.getMessage(), e);
}
return HttpClients.createDefault();
}
public static String buildMap(Map map) {
StringBuffer sb = new StringBuffer();
if (map != null && map.size() > 0) {
for (String key : map.keySet()) {
sb.append(key + "=");
if (null == map.get(key)) {
sb.append("&");
} else {
//代码效果参考:http://www.lyjsj.net.cn/wz/art_22938.html
String value = String.valueOf(map.get(key));try {
value = URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage(), e);
}
sb.append(value + "&");
}
}
}
return sb.toString();
}
/
发送HTTP_GET请求
@see 1)该方法会自动关闭连接,释放资源
@see 2)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串
@see 3)请求参数含中文时,经测试可直接传入中文,HttpClient会自动编码发给Server,应用时应根据实际效果决 定传入前是否转码
@see 4)该方法会自动获取到响应消息头中【Content-Type:text/html; charset=GBK】的charset值作为响应报文的 解码字符集
@see 5)若响应消息头中无Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1作为响应报文的解码字符 集
@param reqURL 请求地址(含参数)
@return 远程主机响应正文 HttpHost proxy = new HttpHost("192.168.15.4", 3128);
/
public static JSONObject sendGetRequest(String reqURL, Map map, HttpHost proxy) {
String param = buildMap(map);
if (null != param) {
reqURL += "?" + param;
}
JSONObject respContent = new JSONObject(); // 响应内容
// reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET);
HttpGet httpget = new HttpGet(reqURL);
httpget.setHeader("Connection", "close");
CloseableHttpResponse response = null;
try {
response = createSSLClientDefault(proxy).execute(httpget, HttpClientContext.create()); // 执行GET请求
HttpEntity entity = response.getEntity(); // 获取响应实体
if (null != entity) {
Charset respCharset = Charset.forName(ENCODE_CHARSET);
respContent = JSONObject.fromObject(EntityUtils.toString(entity, respCharset), getJsonConfig());
log.info("发送get请求返回结果:{}", respContent);
EntityUtils.consume(entity);
} else {
log.error("发送get请求返回错误:{}", response);
}
} catch (ConnectTimeoutException cte) {
log.error("请求通信【" + reqURL + "】时连接超时,堆栈轨迹如下", cte);
respContent.put(CODE, -1000);
respContent.put(MSG, cte.getMessage());
} catch (SocketTimeoutException ste) {
log.error("请求通信【" + reqURL + "】时读取超时,堆栈轨迹如下", ste);
respContent.put(CODE, -1000);
respContent.put(MSG, ste.getMessage());
} catch (ClientProtocolException cpe) {
log.error("请求通信【" + reqURL + "】时协议异常,堆栈轨迹如下", cpe);
respContent.put(CODE, -1000);
respContent.put(MSG, cpe.getMessage());
} catch (ParseException pe) {
log.error("请求通信【" + reqURL + "】时解析异常,堆栈轨迹如下", pe);
respContent.put(CODE, -1000);
respContent.put(MSG, pe.getMessage());
} catch (IOException ioe) {
log.error("请求通信【" + reqURL + "】时网络异常,堆栈轨迹如下", ioe);
respContent.put(CODE, -1000);
respContent.put(MSG, ioe.getMessage());
} catch (Exception e) {
log.error("请求通信【" + reqURL + "】时偶遇异常,堆栈轨迹如下", e);
respContent.put(CODE, -1000);
respContent.put(MSG, e.getMessage());
} finally {
try {
if (response != null)
response.close();
} catch (IOException e) {
e.printStackTrace();
}
if (httpget != null) {
httpget.releaseConnection();
}
}
return respContent;
}
/
将null值的字段去掉
@return
/
private static JsonConfig getJsonConfig() {
JsonConfig jsonConfig = new JsonConfig();
jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
@Override
public boolean apply(Object arg0, String arg1, Object arg2) {
return StringUtils.equals("null", String.valueOf(arg2));
}
});
return jsonConfig;
}
/*
发送HTTP_POST请求 type: 默认是表单请求,
@see 1)该方法允许自定义任何格式和内容的HTTP请求报文体
@see 2)该方法会自动关闭连接,释放资源
@see 3)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串
@see 4)请求参数含中文等特殊字符时,可直接传入本方法,并指明其编码字符集encodeCharset参数,方法内部会自 动对其转码
@see 5)该方法在解码响应报文时所采用的编码,取自响应消息头中的【Content-Type:text/html; charset=GBK】的 charset值
@see 6)若响应消息头中未指定Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1
@param reqURL 请求地址
@param param 请求参数,若有多个参数则应拼接为param11=value11&22=value22&33=value33的形式
@param type 编码字符集,编码请求数据时用之,此参数为必填项(不能为""或null)
@return 远程主机响应正文
/
public static JSONObject sendPostRequest(String reqURL, Map map, String type, HttpHost proxy) {
JSONObject respContent = new JSONObject();
// 设置请求和传输超时时间
HttpPost httpPost = new HttpPost(reqURL);
httpPost.setHeader("Connection", "close");
// 这就有可能会导致服务端接收不到POST过去的参数,比如运行在Tomcat6.0.36中的Servlet,所以我们手工指定CONTENT_TYPE头消息
if (type != null && type.length() > 0) {
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json; charset=" + ENCODE_CHARSET);
} else {
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=" + ENCODE_CHARSET);
}
CloseableHttpResponse response = null;
try {
// 判断map不为空
if (map != null) {
// 声明存放参数的List集合
List params = new ArrayList();
// 遍历map,设置参数到list中
for (Map.Entry entry : map.entrySet()) {
if (null != entry.getValue()) {
params.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
}
}
// 创建form表单对象
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, ENCODE_CHARSET);
formEntity.setContentType("Content-Type:application/json");
// 把表单对象设置到httpPost中
httpPost.setEntity(formEntity);
}
// reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET);
response = createSSLClientDefault(proxy).execute(httpPost, HttpClientContext.create());
HttpEntity entity = response.getEntity();
if (null != entity) {
respContent = JSONObject.fromObje